The*_*ude 0 c++ java math calculator double-precision
我目前正在用java编写计算器程序.这是我的第一个java程序,我习惯于c ++.
我注意到java中的双打完全不像c ++中的双打.在java和c ++
4.1*3
中尝试这个/ .1
它应该是
12.3然后123,并且c ++给出了这个结果但java给出了
12.299999999999999和122.99999999999999
我怎么能像在c ++中使用双打一样进行数学运算,我知道你在程序中使用12.299999999999999的任何东西都不会与12.3相比没有区别,但是当用户正在阅读数字时,这非常难看.我已经查看了BigDecimal类,但我无法对该类执行trig和logarithms等等
那么,为什么这不精确呢?:4.1
已经不能精确表示为二进制数(无论是固定点还是浮点数),因此它会舍入到下一个double
值.将此乘以3并不会改变不可表示性的事实,但会放大错误,因此它现在是一个不同的二进制值,而不是从十进制转换12.3
得到的.因此,当再次将其转换为十进制时,您会获得具有大量九的数字.
当它与10相乘时,您只需将误差再次放大10.(再次除以0.1会引入更多错误,因为它0.1
也不能完全表示.)
您的C++程序可能使用完全相同的操作.在Java中显示不同的原因是它显示了从字符串中重现数字所需的所有数字,而您的C++输出函数以某种方式对其进行舍入.(由于您没有显示输出代码,我们无法确定您在那里做了什么.)
输出要消化的人类用户的数字时,请使用NumberFormat
(在java.text中)或a Formatter
(在java.util中).
我注意到 java 中的双精度数与 c++ 中的双精度数完全不同。
事实上,Java 将使用与 C++ 1完全相同的双精度表示,并且算术将(很可能)在内部产生完全相同的值。
这里的根本问题是二进制浮点数表示和十进制表示之间不存在精确的一对一映射。诸如此类的数字12.3
无法精确表示为二进制浮点数。这在数学上是不可能的。
要理解这一点(而且您应该),请阅读“每个计算机科学家应该了解的浮点运算知识”。
您观察到的差异将是由于将双精度值转换为数字以进行输出的格式代码的差异所致。在 Java 的情况下,代码给出了它可以实现的实际双精度数的最准确的十进制表示。在 C++ 情况下,它对最低有效数字进行四舍五入...这给出了您期望的数字,但不是最准确的十进制表示形式。
这两种方法都没有错。他们只是不同。如果您希望 Java 显示四舍五入到特定位数的数字,您可以使用 Java 格式化程序类之一来完成此操作。
另一种选择是使用该类在 Java 中执行所有计算器算术BigDecimal
。这将为您提供精确的数字,以您在高中学到的十进制算术的局限性为模;例如,您无法精确地用十进制表示 1/3 之类的分数。缺点是BigDecimal
算术比浮点慢很多数量级,而且 API 使用起来更麻烦。
1 - 我最近了解到这可能不正确。事实上,一些C++ 编译器在计算(某些)表达式时会使用 80 位“扩展”浮点。不幸的是,没有指定精确的行为,这意味着用 C++ 编写的浮点代码可能会根据编译器供应商、编译选项等给出不同的结果。