我正在开发一个小型Java程序,在某个地方,我的计算出错了。我的代码如下:
import java.io.*;
import java.util.*;
import java.text.*;
public class NumManip
{
public static void main(String args[])
{
Scanner numGetter = new Scanner(System.in);
final int MULT_1 = 9;
final int MULT_2 = 12345679;
final int MULT_3 = 1000;
int poorHatedNumber;
System.out.print("Enter a digit between 1 and 9 that you dislike: ");
poorHatedNumber = numGetter.nextInt();
int num1 = poorHatedNumber * MULT_1, num2 = num1 * MULT_2;
long num3 = num2 * MULT_3;
System.out.println();
System.out.println(" " + poorHatedNumber);
System.out.println(" " + "x" + MULT_1);
System.out.println(" __");
System.out.println(" " + num1);
System.out.println(" x" + MULT_2);
System.out.println(" __");
System.out.println(" " + num2);
System.out.println(" x" + MULT_3);
System.out.println("____________");
System.out.println(num3);
}
}
我尝试在屏幕上打印num1,num2和num3以查看问题所在,而num1是正确的,num2是正确的,而num3是怪异的。我的输入是9,第一次计算乘以9得到81.然后它乘以12345679得到999999999,然后它乘以1000得到-727380968。最后一步出了什么问题?我真的是Java的新手,我没有遇到这个问题。
答案 0 :(得分:1)
999999999 * 12345679 = 1.234567898765432e + 16大于int
的最大值2,147,483,647
由于Java使用2-compliment method to store int number(意味着当数字为负时最左边的位被打开),这个计算“溢出”(残留)到该位,导致负面结果。
对于如此大的数字进行计算,您应该使用 BigDecimal
答案 1 :(得分:0)
由于num2和num1都是整数,所以发生了整数乘法,它超过了整数值的最大值。
long num3 = (long)num2 * MULT_3;
答案 2 :(得分:0)
我认为你得到的数字大于数据类型可以处理的数字,并且当数据类型被签名时,它会包含在负数中。
答案 3 :(得分:0)
别担心,这真的不是一个愚蠢的错误。整个“数字通常是一个固定的大小” - 最初只会让每个人感到困惑。现在你知道了什么,这里甚至更奇怪。这不是你的问题的答案,但是现在你刚刚看到一个“糟糕的溢出”的例子,你可能会觉得这很有趣。
考虑一个奇数x
。有一个y
,x * y == 1
。这个数字y
被称为modular multiplicative inverse,它可以很容易地计算出来(参见Hacker's Delight,精确除以常数)。这看起来可能是非常直观的,因为它实际上允许一种奇怪的类型“除法”,只有在数字是除数的精确倍数时才有效,并且通常它允许您“乘以”奇数的乘法。例如,如果你有a = 3 * b
,那么b = -1431655765 * a
- 无论乘法是否有任何溢出,所以溢出不一定是“破坏性的”。