双倍乘以100,然后投给长是给错误的价值 [英] Double multiplied by 100 and then cast to long is giving wrong value

查看:144
本文介绍了双倍乘以100,然后投给长是给错误的价值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

  Double i = 17.31; 
long j =(long)(i * 100);
System.out.println(j);

O / P: 1730 //预计:1731

  Double i = 17.33; 
long j =(long)(i * 100);
System.out.println(j);

O / P: 1732 //预计:1733

  Double i = 17.32; 
long j =(long)(i * 100);
System.out.println(j);

O / P: 1732 //预计值:1732 / code>

  Double i = 15.33; 
long j =(long)(i * 100);
System.out.println(j);

O / P: 1533 //预计:1533 {按预期} / code>



我曾尝试Google,但无法找到原因。如果问题不大,我很抱歉。

解决方案

没有一个答案似乎处理为什么 17.32 行事不同。

1。为什么发生?

您在 17.32 17.33& 17.31 是由于IEEE-754 四舍五入规则导致的。

舍入规则适用于: Java™虚拟
机器规格
§2.8.1


Java虚拟机的舍入操作总是使用IEEE
754舍入到最近的模式。不精确的结果四舍五入到最接近的
可表示的值,并且带有以
最低有效位为零的值。这是IEEE 754默认模式。 Java虚拟
机器不给出任何方法来改变浮点四舍五入
模式


$ b $ hr

2。您的情况:

Double是:(1符号位+11指数位+52分数位= 64位)。 -00]
符号指数分数

17.31 - > 0(+)10000000011(+4)1.0001010011110101110000101000111101011100001010001111
17.32 - > 0(+)10000000011(+4)1.0001010100011110101110000101000111101011100001010010 //向上舍入
17.33 - > 0(+)10000000011(+4)1.0001010101000111101011100001010001111010111000010100






3。内部表述(证明):

17.31 :(尾数比较)

 实际:1.00010100111101011100001010001111010111000010100011110 ... 
内部:1.0001010011110101110000101000111101011100001010001111



17.32 :(尾数比较)

 实际值:1.00010101000111101011100001010001111010111000010100011 ... 
内部值:1.0001010100011110101110000101000111101011100001010010 //取整值!

17.33:(尾数比较)

 实际:1.00010101010001111010111000010100011110101110000101000 ... 
内部:1.0001010101000111101011100001010001111010111000010100






4。转换回十进制:



  17.31  - > 17.309999999999998721023075631819665431976318359375 ... 
17.32 - > 17.32000000000000028421709430404007434844970703125 ... //(被四舍五入)
17.33 - > 17.3299999999999982946974341757595539093017578125 ...



5。 @Jeppe Stig Nielsen表示,在你的乘法步骤中还有一个更重要的因素。 FP 乘法的结果( 参考 )步骤自己向最近的方向舍入。
这改变了哪个结果是预期的,哪些不是,但是其原因仍然与上述完全相同。


$ b 最后,由于(long)
的转换,会出现截断,并将结果留给您看。 (1730,1732,1732)



缩小基元转换: Java™语言规范 §5.1.3


如果浮点数不是无穷大,浮点数
被四舍五入为整数值V,使用
四舍五入IEEE 754 round-to-zero模式


I have the following code:

Double i=17.31;
long j=(long) (i*100);
System.out.println(j);

O/P : 1730 //Expected:1731

Double i=17.33;
long j=(long) (i*100);
System.out.println(j);

O/P : 1732 //Expected:1733

Double i=17.32;
long j=(long) (i*100);
System.out.println(j);

O/P : 1732 //Expected:1732{As expected}

Double i=15.33;
long j=(long) (i*100);
System.out.println(j);

O/P : 1533 //Expected:1533{as Expected}

I have tried to Google but unable to find reason.I am sorry if the question is trivial.

解决方案

None of the answers seem to deal with why 17.32 acted different.

1. Why it occurred

The difference in behaviour you see between 17.32 and 17.33 & 17.31 is due to IEEE-754 Rounding rules.

Rounding rule applied: from, The Java™ Virtual Machine Specification §2.8.1

The rounding operations of the Java virtual machine always use IEEE 754 round to nearest mode. Inexact results are rounded to the nearest representable value, with ties going to the value with a zero least-significant bit. This is the IEEE 754 default mode. The Java virtual machine does not give any means to change the floating-point rounding mode


2. Your case:

Double is: (1 sign-bit + 11 exponent-bits + 52 fraction-bits = 64bits). Internal representation after rounding below:

             1 [63]      11 [62-52]           52 [51-00]
              Sign        Exponent             Fraction

17.31 -->    0 (+)       10000000011 (+4)     1.0001010011110101110000101000111101011100001010001111
17.32 -->    0 (+)       10000000011 (+4)     1.0001010100011110101110000101000111101011100001010010 //rounded up
17.33 -->    0 (+)       10000000011 (+4)     1.0001010101000111101011100001010001111010111000010100


3. Internal representation (Proof):

17.31: (Mantissa comparison)

Actual:   1.00010100111101011100001010001111010111000010100011110...
Internal: 1.0001010011110101110000101000111101011100001010001111

17.32: (Mantissa comparison)

Actual:   1.00010101000111101011100001010001111010111000010100011... 
Internal: 1.0001010100011110101110000101000111101011100001010010    //round-up!

17.33: (Mantissa comparison)

Actual:   1.00010101010001111010111000010100011110101110000101000...
Internal: 1.0001010101000111101011100001010001111010111000010100


4. Conversion back-to-decimal:

17.31 ->  17.309999999999998721023075631819665431976318359375...
17.32 ->  17.32000000000000028421709430404007434844970703125... //(was rounded up)
17.33 ->  17.3299999999999982946974341757595539093017578125...

(IEEE-754 Analysis Tool)

5. Cast to long

EDIT: There is a factor more at play at your multiplication step as @Jeppe Stig Nielsen said. The result of the FP multiplication (Reference) step does its own rounding-towards-nearest. This changes which results are as expected and which aren't, but the reason is still exactly the same as stated above.

Finally, due to the cast (long), truncation occurs, and leaves you with the results you see. (1730, 1732, 1732)

Narrowing Primitive Conversion : The Java™ Language Specification §5.1.3

If the floating-point number is not an infinity, the floating-point value is rounded to an integer value V, rounding toward zero using IEEE 754 round-toward-zero mode

这篇关于双倍乘以100,然后投给长是给错误的价值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆