为啥以下语句在 Java 中给出不同的输出?

Posted

技术标签:

【中文标题】为啥以下语句在 Java 中给出不同的输出?【英文标题】:Why do the following statements give different outputs in Java?为什么以下语句在 Java 中给出不同的输出? 【发布时间】:2020-04-07 14:39:28 【问题描述】:

对于 x 的某些值(x 是 long 类型),

 x %= (1e9+7);

 x %= 1_000_000_007;

给出不同的答案。知道为什么会这样吗?

另外,这种下划线格式 (1_000_000_007) 在不同语言中是否通用?除了增强可读性之外,它还有其他优点吗?

【问题讨论】:

第一个值1e9+7double,第二个值1_000_000_007intx的类型是什么? x 是 long 类型 明白了。 x的值是多少,对x进行两次操作的结果分别是什么? 正如你所指出的,我认为问题是由于 double vs int。我没有x 的值,但是如果我使用 double 值,mod 之后的值是 862275785,如果我们使用 int 值,则为 862275791。 6 的差异是由浮点运算引起的。见:Is floating point math broken? 【参考方案1】:

这是因为1e9double 文字,并不是每个long 值都可以精确表示为double,因此由于从long 到的隐式转换会导致精度损失double.

According to the language specification,x %= d 等价于 x = (long) (x % d),当 xlong 类型的变量并且 ddouble 类型时。余数运算还对操作数执行binary numeric prommotion,将x 转换为double 类型。

由于double 是双精度IEEE 754 floating-point number,它的尾数精度为53 位,不足以表示long 值可能需要的所有64 位精度。换句话说,doublelong 都使用 64 位,但有许多 double 值不是 long 值,因此也必须有许多 long 值不是 double 值。因此,从 longdouble 的隐式转换可能会导致大于 253 或小于 -253 的值丢失精度。

顺便说一句,由于余数运算,由于精度损失导致的误差可能高达 109 + 7 本身。例如,对于输入值9_223_372_036_563_603_804L,错误为999_999_659

【讨论】:

以上是关于为啥以下语句在 Java 中给出不同的输出?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Arrays.toString() 会给出与手动打印数组不同的输出? [关闭]

为啥 Arduino IDE 中的相同代码在不同的笔记本电脑上给出不同的输出?

Java中从字符串到sql日期的日期转换给出不同的输出? [复制]

为啥 QDatastream 没有给出正确的输出

为啥 printf() 在 python 中给出一个奇怪的输出?

为啥 ('1'+'1') 在 Java 中输出 98? [复制]