这似乎是一个非常愚蠢的问题,但我今天遇到了一些神秘且看似美丽的东西。我试着用谷歌搜索,我无法挖掘任何东西。
我知道0.1不能用二进制表示。而且,当我运行以下代码时:
double g = 1.0;
System.out.println(g);
g = g/10;
System.out.println(g);
g = g*3;
System.out.println(g);
这会产生输出:
1.0
0.1
0.30000000000000004
第一个输出和第三个输出是预期的,但第二个输出是怎么回事?为什么这么正确?这应该是不可能的,然而就是这样。
答案 0 :(得分:1)
数字促销规则
答案 1 :(得分:1)
为什么这样,是的,对吗?
如您所述,许多十进制浮点数不能表示为二进制浮点数,反之亦然。
当你写这样的陈述时:
double g = 0.1;
将十进制值转换为最接近的二进制浮点值。然后当你像这样打印它
System.out.println(g);
格式化程序根据以下规则生成最接近的十进制浮点值:
小数部分必须打印多少位数?必须至少有一个数字来表示小数部分,并且除此之外必须有多个,但只有多少,更多的数字才能唯一地将参数值与double类型的相邻值区分开来。
(参考:Double.toString(double)
javadoc)
这意味着您将经常获取您开始使用的十进制数的精确十进制表示。
简单来说,从十进制转换为二进制时的错误与从二进制转换为十进制时的错误相同。错误“取消”。
现在,这并不总是发生。通常,计算中的累积误差足够大,十进制(和二进制)结果中的误差将在输出中显而易见。
答案 2 :(得分:0)
让我们逐行逐步完成计算:
$("#communitymembers").append(memberslist);
$container.isotope();
g是完全代表1.0的float64数字。
double g = 1.0;
右操作数转换为double,因此精确到10.0。
除法运算以无限精度(概念上)执行,然后四舍五入到最接近的float64数字作为结果。
确切的答案显然是0.1。但最接近的float64数字为0.1正好是7205759403792794/256。
因此g = 0.10000000000000000555111512312578 ...(更多数字)。如果要打印全精度精确值,请查看新的BigDecimal(g)。
g = g / 10;
同样,右操作数被转换为3.0精确。我们将0.1000000000000000055511151231257(...)乘以3得到0.3000000000000000166533453693773(...)。
现在g的值恰好是5404319552844596/2 54 。