为啥以下语句在 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+7
是double
,第二个值1_000_000_007
是int
。 x
的类型是什么?
x 是 long 类型
明白了。 x
的值是多少,对x
进行两次操作的结果分别是什么?
正如你所指出的,我认为问题是由于 double vs int。我没有x
的值,但是如果我使用 double 值,mod 之后的值是 862275785,如果我们使用 int 值,则为 862275791。
6
的差异是由浮点运算引起的。见:Is floating point math broken?
【参考方案1】:
这是因为1e9
是double
文字,并不是每个long
值都可以精确表示为double
,因此由于从long
到的隐式转换会导致精度损失double
.
According to the language specification,x %= d
等价于 x = (long) (x % d)
,当 x
是 long
类型的变量并且 d
是 double
类型时。余数运算还对操作数执行binary numeric prommotion,将x
转换为double
类型。
由于double
是双精度IEEE 754 floating-point number,它的尾数精度为53 位,不足以表示long
值可能需要的所有64 位精度。换句话说,double
和 long
都使用 64 位,但有许多 double
值不是 long
值,因此也必须有许多 long
值不是 double
值。因此,从 long
到 double
的隐式转换可能会导致大于 253 或小于 -253 的值丢失精度。
顺便说一句,由于余数运算,由于精度损失导致的误差可能高达 109 + 7 本身。例如,对于输入值9_223_372_036_563_603_804L
,错误为999_999_659
。
【讨论】:
以上是关于为啥以下语句在 Java 中给出不同的输出?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Arrays.toString() 会给出与手动打印数组不同的输出? [关闭]
为啥 Arduino IDE 中的相同代码在不同的笔记本电脑上给出不同的输出?
Java中从字符串到sql日期的日期转换给出不同的输出? [复制]