对于使用Java制作的更改应用程序,我在计算double值中的小数位数时遇到问题。
双值表示金钱,因此我的所有操作都必须在对原始值进行操作后将12.58之类的双值存储为12.5797886。为了抵消这种影响,我选择使用String,就像这样:
String amountString = String.valueOf(amount);
String decimals = amountString.substring(amountString.indexOf('.') + 1);
因此,如果金额是12.58,我获得58而不是57978 ...
我的问题涉及大额,就像12849561476651.2501535这样的金额在科学记数法中转换,同时存储在双。所以金额的双倍值将是1.284956147665125E13
不幸的是,我不能只计算点后面的数字,并在位置13之后取一切。在这样的情况下,原始小数2501535在第三个位置包含0,结果在位置13之后四舍五入到25。
我为想要在没有科学记数法的情况下打印小数值的人找到了一些解决方案,他们使用.printf(%f,...)或类似的东西。
但是,如果有可能,我如何计算双值中包含的小数位数并处理存储问题和科学记数法?
我必须能够知道是否有超过2位小数。此外,如果你有一个非常高性能的解决方案,即使它是复杂的或奇怪的解决方案,它也会很棒。
谢谢
答案 0 :(得分:2)
不要使用double或float来存储货币,也不要存储任何需要精确的十进制数,因为double和float可能不准确。
您可以使用BigDecimal或使用int或long并自行跟踪小数点。
有关这方面的更多信息,请参阅Joshua Bloch撰写的有效Java中的“项目48:避免浮动和双重(如果需要确切答案)”部分:http://uet.vnu.edu.vn/~chauttm/e-books/java/Effective.Java.2nd.Edition.May.2008.3000th.Release.pdf
答案 1 :(得分:1)
不要使用浮动或双倍进行金融操作。
最好使用BigDecimal
。
BigDecimal
为您提供所需的精确度。来自javadoc:
任意精度带符号的十进制数
由于双精度的内部二进制表示的近似,double会产生错误。此外,对于非常小的值,它可能会产生很难找到的错误。
答案 2 :(得分:1)
你不能。浮点没有小数位。它有二进制位置,并且它们与小数位无法相称。如果你想要小数位,你必须使用十进制基数。
使用BigDecimal.
编辑在您自此回答后添加的段落中以及您现在已删除的段落中,您声明该号码来自用户界面。在这种情况下,此时它是String
,已经在基数-10中,所以你应该只计算String
中的小数位,而不是转换它一双。