[英]Is storing currency in Java double (floating point), without any math, always accurate?
當然不應該做數學,因為結果不會准確。 浮點值不適用於此。
但是僅僅存儲值呢? 就我個人而言,對於 String 或 Long,我會使用 go,但看起來我有時可能被迫與堅持使用浮點類型的系統進行交互。
看起來0.00 到 2.00 之間的值是 100% 准確的 - 請參見下面的代碼。 但真的是這樣嗎? 為什么? 當我簡單地做double v = 0.01
時不應該已經有問題了嗎?
public static void main(final String[] args) {
final DecimalFormat df = new DecimalFormat("0.0000000000000000000000000", DecimalFormatSymbols.getInstance(Locale.US));
final BigDecimal aHundred = new BigDecimal("100");
final BigDecimal oneHundredth = BigDecimal.ONE.divide(aHundred);
for (int i = 0; i < 200; i++) {
BigDecimal dec = oneHundredth;
for (int ii = 0; ii < i; ii++) {
dec = dec.add(oneHundredth);
}
final double v = dec.doubleValue();
System.err.println(v);
System.err.println(df.format(v));
}
System.exit(0);
}
Output:
0.01
0.0100000000000000000000000
0.02
0.0200000000000000000000000
0.03
0.0300000000000000000000000
...
1.38
1.3800000000000000000000000
1.39
1.3900000000000000000000000
1.4
1.4000000000000000000000000
1.41
1.4100000000000000000000000
...
1.99
1.9900000000000000000000000
2.0
2.0000000000000000000000000
從十進制轉換為基於二進制的浮點數或反之亦然是數學。 它是一種將結果舍入到最接近的可表示值的操作。
當您將 .01 轉換為double
時,結果正好是 0.01000000000000000020816681711721685132943093776702880859375。 Java 的默認顯示格式可能顯示為“0.01”,但實際值為 0.01000000000000000020816681711721685132943093776702880859375。
Java 的double
精度格式的精度是這樣的,如果任何具有最多 15 個有效小數位的十進制數字四舍五入到最接近的可表示double
精度,然后將該double
精度四舍五入到最接近的具有 15 個或更少有效數字的十進制數字,結果將是原號碼。
因此,您可以使用double
來存儲最多 15 位有效數字(在指數范圍內)的任何十進制數字,並且可以通過將其轉換回十進制來恢復原始數字。 超過 15 位數字,一些數字將被往返更改。
將貨幣存儲在 Java double(浮點數)中,沒有任何數學運算,總是准確的嗎?
如果您將貨幣值表示為最小貨幣單位(例如,美分)的倍數,那么您實際上可以使用 53 位精度……計算結果為 9.0 x 10 15美分,或 9.0 x 10 13美元。
(就規模而言,美國國債目前約為 2.8 x 13美元。)
如果您嘗試用(比如)浮點美元(使用double
)表示貨幣值,那么大多數美分值根本無法精確表示。 只有 25 美分的倍數可以精確表示為二進制浮點數。
簡而言之,即使您不對值執行算術運算,它也可能不精確。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.