Using float and double for calculation, giving different results
我正在做一个项目,我们用8位小数点计算项目的价格。但有时计算结果不同。
我尝试了一些样本,但得到了不同的计算结果:
1 2 3 4 5 6 7 8
| public static void main (String[] args ) {
double value1 = 0.999939f * 0.987792f ;
double value2 = 0.999939 * 0.987792;
double value3 = (double)0.999939f * 0.987792f ;
System. out. println("value 1 :"+ value1 );
System. out. println("value 2:"+ value2 );
System. out. println("value 3 :"+ value3 );
} |
输出是:
1 2 3
| value 1 : 0.9877317547798157
value 2 : 0.9877317446880001
value 3 : 0.9877317839126931 |
这三个结果是不同的。
我很困惑。有人能告诉我这里发生了什么吗?谢谢。
我看了一些已经回答过的问题,但我只想找到一些我可以用浮点和双精度计算的方法。否则我得换很多地方。会很痛苦的。
- 不要使用双精度或浮点型变量来表示货币量。您将遇到许多与舍入等相关的问题。请改用BigDecimal类。
- 谢谢@rafaelosipov。我还有一些疑问。我们能确定小数点的位置吗?它会影响计算和舍入吗?Java提供了任何可以帮助的API?
- @real怀疑论者这个链接是关于为什么我们不应该使用double或float来表示。这真的很有帮助,下次我不会用浮球和双打。但现在我的问题是,"我能用浮动和双精度来做一些不会影响结果的事情吗?"
- @拉斐洛西波夫在他的评论中已经回答了这一点,我给出的链接提供了其他的可能性,比如使用int或long(long在你的情况下会更好,因为你在小数点后有那么多的位置)。
- 谢谢@realconcentary
- 带小数位数8的BigDecimal适用于小数点后8位小数的精确表示。可以控制舍入模式,但其中一个选项与浮点相同。
- 我看不出这两个问题是如何重复的(它们可能是相关的,但它们没有回答这个特定的问题)。
由于浮点数和小数的表示方式,强制转换可能会导致不同的结果。
for:double value1 = 0.999939f * 0.987792f您将两个浮点数相乘,然后将其转换为双精度浮点数。由此产生的浮点表示是转换为double的表示。
对于:double value2 = 0.999939 * 0.987792;,您将得到两个双精度数,并将其保存为一个双精度数。这是没有强制转换的时候,因此表示永远不会更改(即,数据表示更改不会导致潜在的数据丢失)。
对于:double value3 = (double)0.999939f * 0.987792f;,您将一个由浮点数铸造的双精度数乘以一个浮点数。由于Java数学是如何工作的,第二个浮点数也可能被铸造成一个double,所以现在你正在乘以两个双倍,这是一次浮点,导致第三组表示。
因为浮球和双打有不同的精度,每一个都会得到不同的结果。有关浮点运算的更多信息,请参见此处。
- 为什么你说当涉及双精度时没有潜在的数据丢失?这根本不是真的。
- @Amit您是正确的,当数字以双精度形式记录在表示中,并且有机会在乘法和保存时丢失数据时,可能会丢失数据,但所有这些都在双精度工作方式的定义中。我的意思是,改变表示形式不会丢失数据。我要编辑一下。
当你用"f"字符写一个数字时,它被认为是float,这意味着它是用32位编码的,而没有它,它是用64位编码的double。
位数越多,表示十进制数的精度就越高。这对小数点少的数字没有影响,但在您的例子中,它是重要的。
总之,在代码中只使用double变量。
- 那不准确。浮点表示法(单精度或双精度)的精度受到限制,与小数无关。事实上,自然数也可能不准确。