负数取绝对值时小心越界:如Math.abs(-2147483648)

本文探讨了Java中使用Math.abs()方法时可能遇到的整数溢出问题,特别是当输入值为Integer.MIN_VALUE时导致的结果异常。文章提供了源码分析,并给出了解决建议。

在解题中,遇到使用Math.abs(int n)时,一定要考虑变量越界的问题,比如Math.abs(-2147483648)由于变量越界其结果仍为-2147483648。

1、越界现象:
Math.abs源码:

    public static int abs(int a) {
        return (a < 0) ? -a : a;
    }

-2147483648的绝对值应该是2147483648,但是int类型最大值就为2147483647,在模系统中最大值再加一会变成最小值,是一个首尾相接的循环.

总结:
1、java中使用10亿以上数字时请使用long类型,可以有效避免整数溢出。
2、对Integer.MIN_VALUE取绝对值仍为Integer.MIN_VALUE,(0x80000000按照补码取负规则还是0x80000000)。
————————————————
版权声明:本文为优快云博主「Code-Coke」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/j572864517/article/details/106938237/

private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { isSelecting = true; selectionStart = e.Location; // 记录起点(屏幕坐标) selectionRect = new RectangleF(e.X, e.Y, 0, 0); } } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (isSelecting) { // 计算选框范围(保持正数宽高) selectionRect.Width = e.X - selectionRect.X; selectionRect.Height = e.Y - selectionRect.Y; pictureBox1.Invalidate(); } } private void pictureBox1_MouseUp(object sender, MouseEventArgs e) { var logicRect = new RectangleF( viewport.ScreenToLogic( Point.Round(selectionRect.Location), // 将 PointF 四舍五入为 Point pictureBox1.Size ), new SizeF( selectionRect.Width / viewport.Scale, selectionRect.Height / viewport.Scale )); selectedItems = points.Where(item => { var p1 = new PointF(item.fiveX, item.sexY); var p2 = new PointF(item.eightX, item.nineY); return logicRect.Contains(p1) || logicRect.Contains(p2); }).ToList(); pictureBox1.Invalidate(); if (e.Button == MouseButtons.Left && isSelecting) { isSelecting = false; // 将屏幕坐标转换为数据坐标 var inverseMatrix = currentTransform.Clone(); inverseMatrix.Invert(); PointF[] points = { new PointF(selectionRect.Left, selectionRect.Top), new PointF(selectionRect.Right, selectionRect.Bottom) }; inverseMatrix.TransformPoints(points); // 更新数据范围 dataMinX = Math.Min(points[0].X, points[1].X); dataMaxX = Math.Max(points[0].X, points[1].X); dataMinY = Math.Min(points[0].Y, points[1].Y); dataMaxY = Math.Max(points[0].Y, points[1].Y); pictureBox1.Invalidate(); } } private void PictureBox_MouseWheel(object sender, MouseEventArgs e) { // 计算缩放中心点(转换为数据坐标) var inverseMatrix = currentTransform.Clone(); inverseMatrix.Invert(); PointF[] centerPoint = { new PointF(e.X, e.Y) }; inverseMatrix.TransformPoints(centerPoint); // 调整缩放级别 zoomFactor *= e.Delta > 0 ? 1.1f : 0.9f; zoomFactor = Math.Max(0.1f, Math.Min(zoomFactor, 10f)); // 限制缩放范围 // 更新变换 currentTransform = new Matrix(); currentTransform.Translate(_offsetX, _offsetY); currentTransform.Scale(zoomFactor, zoomFactor); currentTransform.Translate(-centerPoint[0].X, -centerPoint[1].Y, MatrixOrder.Append); pictureBox1.Invalidate(); } private float dataMinX; // 根据实际类型替换为double等 private float dataMaxX; private float dataMinY; private float dataMaxY; private void Form1_Load(object sender, EventArgs e) { _offsetX = 50; // 初始化偏移量 _offsetY = 50; // 初始化偏移量 }OverflowException和IndexOutOfRangeException在代码里怎么解决pictureBox1所写的代码里怎么解决
03-25
package biginteger; import java.util.Arrays; /** * 大整数类,支持符号和任意精度的整数运算 * 使用倒序数组存储数字(个位在索引0位置) */ public class testBigInteger { private int[] digits; // 数字的倒序数组表示 private boolean isNegative; // 符号标志:true表示负数,false表示正数 /** * 构造函数 - 从字符串构造大整数 * @param numberStr 数字字符串,可包含正负号 */ public testBigInteger(String numberStr) { if (numberStr == null || numberStr.isEmpty()) { throw new IllegalArgumentException("Number string cannot be null or empty"); } // 处理符号 if (numberStr.charAt(0) == '-') { this.isNegative = true; numberStr = numberStr.substring(1); } else if (numberStr.charAt(0) == '+') { this.isNegative = false; numberStr = numberStr.substring(1); } else { this.isNegative = false; } // 去除前导零 numberStr = removeLeadingZeros(numberStr); if (numberStr.isEmpty()) { // 如果去除前导零后为空,说明是0 this.digits = new int[]{0}; this.isNegative = false; // 0没有负号 return; } // 转换为倒序数组 this.digits = stringToReverseArray(numberStr); } /** * 构造函数 - 从倒序数组和符号构造大整数 * @param digits 数字的倒序数组 * @param isNegative 是否为负数 */ public testBigInteger(int[] digits, boolean isNegative) { this.digits = removeLeadingZeros(digits); this.isNegative = isNegative; // 如果是0,确保不是负数 if (isZero()) { this.isNegative = false; } } /** * 拷贝构造函数 * @param other 另一个大整数 */ public testBigInteger(testBigInteger other) { this.digits = Arrays.copyOf(other.digits, other.digits.length); this.isNegative = other.isNegative; } /**大数法乘法 * * @param other * @return 两个大整数的积 */ public testBigInteger multipy(testBigInteger other){ int[] result = multipyBigInteger(this.digits,other.digits); boolean resultNegative = this.isNegative != other.isNegative; return new testBigInteger(result,resultNegative); } /** * 大整数加法 * @param other 另一个大整数 * @return 两个大整数的和 */ public testBigInteger add(testBigInteger other) { // 同号相加 if (this.isNegative == other.isNegative) { int[] resultDigits = addAbsolute(this.digits, other.digits); return new testBigInteger(resultDigits, this.isNegative); } // 异号相加转换为减法 if (compareAbsolute(this.digits, other.digits) >= 0) { int[] resultDigits = subtractAbsolute(this.digits, other.digits); return new testBigInteger(resultDigits, this.isNegative); } else { int[] resultDigits = subtractAbsolute(other.digits, this.digits); return new testBigInteger(resultDigits, other.isNegative); } } /** * 大整数减法 * @param other 另一个大整数 * @return 两个大整数的差 */ public testBigInteger subtract(testBigInteger other) { // 转换为加上相反数 testBigInteger negatedOther = new testBigInteger(other.digits, !other.isNegative); return this.add(negatedOther); } /** * 大整数拆分 * @param num 一个大整数 * @return 分治后的两个局部大整数 */ public static testBigInteger[] splitNumber(testBigInteger num) { int n = num.digits.length; int mid = n/2; int[] low = Arrays.copyOfRange(num.digits,0,mid); int[] high = Arrays.copyOfRange(num.digits,mid,n); testBigInteger lowpart = new testBigInteger(low,false); testBigInteger highpart = new testBigInteger(high,false); return new testBigInteger[]{lowpart,highpart}; } /** * Karatsuba算法 * @param other 另一个大整数 * @return 乘法得到的结果 */ public testBigInteger karatsubamultiply(testBigInteger other){ testBigInteger[] p1 = splitNumber(this); testBigInteger p1Low = p1[0]; testBigInteger p1High = p1[1]; testBigInteger[] p2 = splitNumber(other); testBigInteger p2Low = p2[0]; testBigInteger p2High = p2[1]; testBigInteger z1 = p1High.multipy(p2High); testBigInteger z2 = p1Low.multipy(p2Low); testBigInteger z3 = (p1High.add(p1Low)).multipy(p2High.add(p2Low)); testBigInteger middle = z3.subtract(z2).subtract(z1); int n =this.digits.length; int m =n/2; testBigInteger result = z1.shiftLeft(2*m).add(middle.shiftLeft(m)).add(z2); return result; } /** * 左移操作 * @param m 进位的多少 * @return 返回数组*10^m次方后的结果 */ public testBigInteger shiftLeft(int m) { if(m==0) return this; int[] newDigits = new int[this.digits.length+m] ; System.arraycopy(this.digits,0,newDigits,0,this.digits.length); return new testBigInteger(newDigits,false);} /** * 判断是否为零 * @return 如果是零返回true,否则返回false */ public boolean isZero() { for (int digit : digits) { if (digit != 0) return false; } return true; } /** * 获符号 * @return 如果是负数返回-1,如果是正数返回1,如果是0返回0 */ public int signum() { if (isZero()) return 0; return isNegative ? -1 : 1; } /** * 相反数 * @return 当前大整数的相反数 */ public testBigInteger negate() { if (isZero()) { return this; } return new testBigInteger(this.digits, !this.isNegative); } /** * 绝对值 * @return 当前大整数的绝对值 */ public testBigInteger abs() { if (!isNegative) { return this; } return new testBigInteger(this.digits, false); } /** * 比较两个大整数的大小 * @param other 另一个大整数 * @return 如果当前数大于other返回1,等于返回0,小于返回-1 */ public int compareTo(testBigInteger other) { if (this.isNegative && !other.isNegative) return -1; if (!this.isNegative && other.isNegative) return 1; int absCompare = compareAbsolute(this.digits, other.digits); if (this.isNegative) { return -absCompare; } else { return absCompare; } } /** * 转换为字符串表示 * @return 大整数的字符串表示 */ @Override public String toString() { if (isZero()) { return "0"; } StringBuilder sb = new StringBuilder(); if (isNegative) { sb.append('-'); } // 从最高位开始输出 for (int i = digits.length - 1; i >= 0; i--) { sb.append(digits[i]); } return sb.toString(); } /** * 判断是否相等 * @param obj 要比较的对象 * @return 如果相等返回true,否则返回false */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; testBigInteger other = (testBigInteger) obj; return this.isNegative == other.isNegative && Arrays.equals(this.digits, other.digits); } // ========== 私有辅助方法 ========== private static int[] multipyBigInteger(int[]a,int[]b){ int n = a.length+b.length; int[] result =new int[n]; for(int i = 0;i<a.length;i++){ for(int j = 0 ; j<b.length;j++) { result[i+j]+=a[i]*b[j]; } } int carry = 0; for(int i =0;i<result.length;i++) { int total; result[i]+=carry; total = result[i]; carry = total/10; result[i] = total%10; } return removeLeadingZeros(result); } /** * 绝对值加法 */ private static int[] addAbsolute(int[] a, int[] b) { int maxLen = Math.max(a.length, b.length); int[] result = new int[maxLen + 1]; int carry = 0; for (int i = 0; i < maxLen; i++) { int digitA = (i < a.length) ? a[i] : 0; int digitB = (i < b.length) ? b[i] : 0; int sum = digitA + digitB + carry; result[i] = sum % 10; carry = sum / 10; } if (carry > 0) { result[maxLen] = carry; return result; } else { return Arrays.copyOf(result, maxLen); } } /** * 绝对值减法 (a >= b) */ private static int[] subtractAbsolute(int[] a, int[] b) { int maxLen = Math.max(a.length, b.length); int[] result = new int[maxLen]; int borrow = 0; for (int i = 0; i < maxLen; i++) { int digitA = (i < a.length) ? a[i] : 0; int digitB = (i < b.length) ? b[i] : 0; int diff = digitA - digitB - borrow; if (diff < 0) { diff += 10; borrow = 1; } else { borrow = 0; } result[i] = diff; } return removeLeadingZeros(result); } /** * 比较两个绝对值的大小 */ private static int compareAbsolute(int[] a, int[] b) { int lenA = a.length; int lenB = b.length; if (lenA > lenB) return 1; if (lenA < lenB) return -1; // 长度相等,从最高位开始比较 for (int i = lenA - 1; i >= 0; i--) { if (a[i] > b[i]) return 1; if (a[i] < b[i]) return -1; } return 0; // 相等 } /** * 去除数组前导零 */ private static int[] removeLeadingZeros(int[] arr) { int i = arr.length - 1; while (i > 0 && arr[i] == 0) { i--; } return Arrays.copyOf(arr, i + 1); } /** * 去除字符串前导零 */ private static String removeLeadingZeros(String str) { int i = 0; while (i < str.length() - 1 && str.charAt(i) == '0') { i++; } return str.substring(i); } /** * 字符串转换为倒序数组 */ private static int[] stringToReverseArray(String numStr) { int[] arr = new int[numStr.length()]; for (int i = 0; i < numStr.length(); i++) { char c = numStr.charAt(i); if (c < '0' || c > '9') { throw new IllegalArgumentException("Invalid digit: " + c); } arr[numStr.length() - 1 - i] = c - '0'; } return arr; } // ========== 测试代码 ========== public static void main(String[] args) { // 测试基本功能 testBasicOperations(); // 测试大数运算 testLargeNumberOperations(); // 测试边界情况 testEdgeCases(); // 测试乘法 testMultiplication(); // 测试Karastsuba算法 testKaratsubaCases(); } private static void testBasicOperations() { System.out.println("=== 基本功能测试 ==="); testBigInteger a = new testBigInteger("123"); testBigInteger b = new testBigInteger("456"); // 加法测试 testBigInteger sum = a.add(b); System.out.println(a + " + " + b + " = " + sum); // 减法测试 testBigInteger diff = b.subtract(a); System.out.println(b + " - " + a + " = " + diff); // 符号测试 testBigInteger negativeA = new testBigInteger("-123"); System.out.println("负号测试: " + negativeA); // 比较测试 System.out.println(a + " compareTo " + b + " = " + a.compareTo(b)); System.out.println(b + " compareTo " + a + " = " + b.compareTo(a)); System.out.println(a + " compareTo " + a + " = " + a.compareTo(a)); System.out.println(); } private static void testLargeNumberOperations() { System.out.println("=== 大数运算测试 ==="); String num1 = "9876543210123456789"; String num2 = "1234567890123456789"; testBigInteger a = new testBigInteger(num1); testBigInteger b = new testBigInteger(num2); System.out.println("数字1: " + a); System.out.println("数字2: " + b); // 加法 testBigInteger sum = a.add(b); System.out.println("加法结果: " + sum); // 减法 testBigInteger diff1 = a.subtract(b); testBigInteger diff2 = b.subtract(a); System.out.println("减法结果1: " + diff1); System.out.println("减法结果2: " + diff2); // 负数运算 testBigInteger negativeA = new testBigInteger("-" + num1); testBigInteger negativeB = new testBigInteger("-" + num2); System.out.println("负数加法: " + negativeA + " + " + negativeB + " = " + negativeA.add(negativeB)); System.out.println("负数减法: " + negativeA + " - " + negativeB + " = " + negativeA.subtract(negativeB)); System.out.println(); } private static void testEdgeCases() { System.out.println("=== 边界情况测试 ==="); // 零测试 testBigInteger zero = new testBigInteger("0"); testBigInteger num = new testBigInteger("123"); System.out.println("零加法: " + zero + " + " + num + " = " + zero.add(num)); System.out.println("零减法: " + num + " - " + zero + " = " + num.subtract(zero)); System.out.println("零的符号: " + zero.signum()); // 负零测试(应该自动转为正零) testBigInteger negativeZero = new testBigInteger("-0"); System.out.println("负零自动转为: " + negativeZero); // 前导零测试 testBigInteger withLeadingZeros = new testBigInteger("00000123"); System.out.println("前导零处理: " + withLeadingZeros); // 绝对值测试 testBigInteger negativeNum = new testBigInteger("-456"); System.out.println("绝对值: " + negativeNum.abs()); // 相反数测试 System.out.println("相反数: " + num.negate() + ", " + negativeNum.negate()); System.out.println(); } private static void testMultiplication() { System.out.println("=== 乘法测试 ==="); // 基本测试 testCaseMultiply("12", "13", "156"); testCaseMultiply("0", "12345", "0"); testCaseMultiply("999", "0", "0"); // 符号测试 testCaseMultiply("-5", "6", "-30"); testCaseMultiply("7", "-8", "-56"); testCaseMultiply("-9", "-10", "90"); // 大数测试 testCaseMultiply("123456789", "987654321", "121932631112635269"); testCaseMultiply( "999999999999999999999999999999", "555555555555555555555555555555", "555555555555555555555555555554444444444444444444444444444445" ); // 前导零测试 testCaseMultiply("000123", "000456", "56088"); System.out.println(); } private static void testCaseMultiply(String num1, String num2, String expected) { testBigInteger a = new testBigInteger(num1); testBigInteger b = new testBigInteger(num2); testBigInteger product = a.multipy(b); String result = product.toString(); System.out.printf("%s * %s = %s", a, b, result); if (!result.equals(expected)) { System.out.printf(" ✗ 错误!期望值: %s", expected); } System.out.println(); } private static void testKaratsubaCases() { System.out.println("=== Karatsuba 算法测试用例 ==="); // 1. 基础功能测试 System.out.println("\n--- 基础乘法测试 ---"); testBigInteger a = new testBigInteger("1234"); testBigInteger b = new testBigInteger("5678"); testBigInteger karatsubaResult = a.karatsubamultiply(b); testBigInteger traditionalResult = a.multipy(b); System.out.println("Karatsuba: " + a + " × " + b + " = " + karatsubaResult); System.out.println("传统方法: " + traditionalResult); System.out.println("结果一致: " + karatsubaResult.toString().equals(traditionalResult.toString())); // 2. 边界情况测试 System.out.println("\n--- 边界情况测试 ---"); // 零乘法测试 testBigInteger zero = new testBigInteger("0"); testBigInteger num = new testBigInteger("9876"); System.out.println("零乘法: " + zero + " × " + num + " = " + zero.karatsubamultiply(num)); System.out.println("数乘零: " + num + " × " + zero + " = " + num.karatsubamultiply(zero)); System.out.println("零的符号: " + zero.signum()); // 1乘法测试(单位元) testBigInteger one = new testBigInteger("1"); System.out.println("单位元: " + num + " × " + one + " = " + num.karatsubamultiply(one)); // 3. 负数测试 System.out.println("\n--- 负数运算测试 ---"); testBigInteger negA = new testBigInteger("-1234"); testBigInteger negB = new testBigInteger("-5678"); System.out.println("正×负: " + a + " × " + negB + " = " + a.karatsubamultiply(negB)); System.out.println("负×正: " + negA + " × " + b + " = " + negA.karatsubamultiply(b)); System.out.println("负×负: " + negA + " × " + negB + " = " + negA.karatsubamultiply(negB)); System.out.println("负零测试: " + zero.negate() + " × " + num + " = " + zero.negate().karatsubamultiply(num)); // 4. 大数性能测试 System.out.println("\n--- 大数性能对比测试 ---"); testBigInteger largeA = new testBigInteger("123456789012345678901234567890"); testBigInteger largeB = new testBigInteger("987654321098765432109876543210"); long startTime, endTime; // Karatsuba 间测试 startTime = System.nanoTime(); testBigInteger largeKaratsuba = largeA.karatsubamultiply(largeB); endTime = System.nanoTime(); double karatsubaTime = (endTime - startTime) / 1_000_000.0; // ms // 传统方法间测试(仅小数) if (largeA.digits.length <= 10 && largeB.digits.length <= 10) { startTime = System.nanoTime(); testBigInteger largeTraditional = largeA.multipy(largeB); endTime = System.nanoTime(); double traditionalTime = (endTime - startTime) / 1_000_000.0; // ms System.out.println("大数结果: " + largeKaratsuba); System.out.println("Karatsuba耗: " + String.format("%.3f", karatsubaTime) + "ms"); System.out.println("传统方法耗: " + String.format("%.3f", traditionalTime) + "ms"); System.out.println("加速比: " + String.format("%.2fx", traditionalTime/karatsubaTime)); } else { System.out.println("大数: " + largeKaratsuba); System.out.println("Karatsuba耗: " + String.format("%.3f", karatsubaTime) + "ms"); System.out.println("传统方法跳过(数字过大)"); } } } karatsuba算法结果错误
最新发布
12-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值