Java : 如何计算代表货币的双精度值中包含的小数位数?

Java : How to count the number of decimals contained in a double value that represent money?

对于使用 Java 制作的更改应用程序,我在计算双精度值的小数位数时遇到问题。

double 值代表钱,所以我的所有操作都必须在对原始值进行操作后将 12.58 这样的 double 值存储为 12.5797886 的结果。为了抵消这种影响,我选择使用 String,就像这样:

String amountString = String.valueOf(amount);
String decimals = amountString.substring(amountString.indexOf('.') + 1);

所以如果金额是12.58,我得到的是58而不是57978...

我的问题是涉及到大数额,比如12849561476651.2501535这样的数额在以double形式存储的同时转换为科学计数法。所以金额的双倍值为 1.284956147665125E13

不幸的是,我不能只计算点后面的数字并取位置 13 之后的所有内容。在这种情况下,原始小数 2501535 在第三个位置包含 0,结果在位置 13 四舍五入为 25.

我为那些想要在没有科学记数法的情况下打印十进制值的人找到了一些解决方案,他们使用 .printf( %f , ... ) 或类似的东西。

但是,如果可能的话,我如何计算一个双精度值中包含的小数位数并处理存储问题和科学记数法?

我必须能够知道是否有超过 2 位小数。此外,如果您有一个非常高效的解决方案,即使它是一个复杂或奇怪的解决方案,也会很棒。

谢谢

不要使用 double 或 float 来存储货币,或存储任何需要精确的小数,因为 double 和 float 可能不准确。

您可以使用 BigDecimal 或者使用 int 或 long 并自己记录小数点。

有关这方面的更多信息,请参阅 Joshua Bloch 的 Effective Java 中的 "Item 60: Avoid float and double if exact answers are required" 部分:https://kea.nu/files/textbooks/new/Effective%20Java%20%282017%2C%20Addison-Wesley%29.pdf

不要在财务操作中使用浮点数或双精度数。 最好使用 BigDecimalBigDecimal 为您提供所需的精度。来自 javadoc:

arbitrary-precision signed decimal numbers

由于双精度内部二进制表示的近似,双精度会产生错误。同样对于非常小的值,它会产生很难发现的错误。

你不能。浮点数没有小数位。它有二进制位,它们与小数位不相称。如果你想要小数位,你必须使用小数基数。

使用BigDecimal.

EDIT 在您自此回答后添加但现在已删除的段落中,您声明该号码来自 UI。在这种情况下,它在那个时候是 String,它已经在基数 10 中,所以你应该只计算 String、 和 中的小数位根本没有将其转换为双精度数。