如果在Java中乘以两个大数字,避免数字极性反转的最佳方法

Wat*_*att 2 java int

我的问题与此有关 我如何检查Java中的两个数字相乘是否会导致溢出?

在我的应用程序中,x和y是动态计算的,在我的公式中的某处我必须乘以x和y.

     int x=64371;
     int y=64635;

     System.out.println((x*y));
Run Code Online (Sandbox Code Playgroud)

我得错了输出 -134347711

我可以通过更改变量xy类型快速修复上面的内容int,long并获得上述案例的正确答案.但是,没有出示担保说xy不会增长超过最大容量long为好.

  1. 为什么我在这里得到一个负数,即使我没有将最终结果存储在任何变量中?(为了好奇)

  2. 因为,我不会提前知道x和y的值,有没有更快的方法来避免这种溢出.也许通过将所有x和y除以某个大常数来整个应用程序运行,或者我应该log在乘以它们之前采用x和y?(实际问题)

编辑:

澄清

应用程序在大数据集上运行,这需要数小时才能完成.拥有一个不太慢的解决方案会更好.

由于最终结果用于比较(它们只需要与原始结果成比例),如果能够获得巨大的性能提升,则最终值中的误差±5%是可以接受的.

chr*_*ke- 6

如果您知道数字可能很大,请BigInteger改用.保证不会溢出,然后您可以检查结果是否太大而无法放入intlong,或者您可以直接使用该BigInteger值.

BigInteger是一个任意精度等级,所以它会比使用直接原始值(这大概可以存储在处理器寄存器)慢,所以弄清楚你是否正在切实将要溢出一个long(一个intint永远会适合a long),并选择BigInteger您的域名是否真的需要它.

  • 值得注意的是,与原始类型相比,"BigInteger"具有较大的速度损失. (4认同)

das*_*ght 5

  1. 由于整数溢出,您得到负数:使用二进制补码表示,Java将最高有效位设置1为负数的任何整数解释.
  2. 有一些非常聪明的方法涉及位操作,用于检测加法或减法会导致溢出或下溢的情况.如果您不知道结果有多大,最好切换到BigInteger.但是,您的代码看起来会非常不同,因为Java缺少运算符重载功能,这会使BigInteger对象的数学运算看起来很熟悉.代码也会慢一些.但是,您将保证不会出现溢出和下溢.

编辑:

如果能够获得巨大的性能提升,那么最终值的误差为±5%是可以接受的.

+ -5%的错误是一个巨大的错误补贴!如果您的系统确实可以接受,那么使用double甚至float可以使用.这些类型是不精确的,但它们的范围远大于a的范围int,并且它们不会如此容易地溢出.但是,您必须非常小心,因为浮点数据类型本质上是不精确的.您需要始终牢记数据的表示方式,以避免常见的精度问题.