复合主键 复合外键_复合双重错误
復(fù)合主鍵 復(fù)合外鍵
總覽
在上一篇文章中,我概述了為什么BigDecimal大部分時間都不是答案。 盡管可以構(gòu)造double會產(chǎn)生錯誤的情況,但在BigDecimal遇到錯誤的情況下構(gòu)造情況也一樣容易。
BigDecimal更容易正確,但更容易出錯。
軼事證據(jù)表明,初級開發(fā)人員在正確使用BigDecimal時并不會比在四舍五入時獲得雙倍麻煩。 但是,我對此表示懷疑,因?yàn)樵贐igDecimal中,錯誤也容易被忽略。
讓我們以這個例子為例,其中double產(chǎn)生錯誤的答案。
double d = 1.00; d /= 49; d *= 49 * 2; System.out.println("d=" + d);BigDecimal bd = BigDecimal.ONE; bd = bd .divide(BigDecimal.valueOf(49), 2, BigDecimal.ROUND_HALF_UP); bd = bd.multiply(BigDecimal.valueOf(49*2)); System.out.println("bd=" + bd);版畫
d=1.9999999999999998 bd=1.96在這種情況下,double看起來是錯誤的,它需要四舍五入,這將給出正確的答案2.0。 但是BigDecimal看起來正確,但這不是由于表示錯誤。 我們可以更改除法以使用更高的精度,但是盡管可以控制該誤差有多小,但總會出現(xiàn)表示錯誤。
您必須確保數(shù)字是實(shí)數(shù)并使用四舍五入。
即使使用BigDecimal,也必須使用適當(dāng)?shù)纳崛搿?假設(shè)您有一筆$ 1,000,000的貸款,并且每天要申請0.0005%的利息。 該帳戶只能有一個整數(shù),因此需要四舍五入才能使這筆錢成為實(shí)際金額。 如果不這樣做,需要多長時間才能產(chǎn)生1美分的差異?
double interest = 0.0005; BigDecimal interestBD = BigDecimal.valueOf(interest);double amount = 1e6; BigDecimal amountBD = BigDecimal.valueOf(amount); BigDecimal amountBD2 = BigDecimal.valueOf(amount);long i = 0; do {System.out.printf("%,d: BigDecimal: $%s, BigDecimal: $%s%n", i, amountBD, amountBD2);i++;amountBD = amountBD.add(amountBD.multiply(interestBD).setScale(2, BigDecimal.ROUND_HALF_UP));amountBD2 = amountBD2.add(amountBD2.multiply(interestBD));} while (amountBD2.subtract(amountBD).abs().compareTo(BigDecimal.valueOf(0.01)) < 0); System.out.printf("After %,d iterations the error was 1 cent and you owe %s%n", i, amountBD);最終打印
8: BigDecimal: $1004007.00, BigDecimal: $1004007.00700437675043756250390625000000000000000 After 9 iterations the error was 1 cent and you owe 1004509.00您可以四舍五入結(jié)果,但是即使您使用BigDecimal,這也掩蓋了您實(shí)際損失一分錢的事實(shí)。
double最終出現(xiàn)表示錯誤
即使您使用適當(dāng)?shù)纳崛?#xff0c;double也會給您不正確的結(jié)果。 它比上一個示例晚得多。
double interest = 0.0005; BigDecimal interestBD = BigDecimal.valueOf(interest); double amount = 1e6; BigDecimal amountBD = BigDecimal.valueOf(amount); long i = 0; do {System.out.printf("%,d: double: $%.2f, BigDecimal: $%s%n", i, amount, amountBD);i++;amount = round2(amount + amount * interest);amountBD = amountBD.add(amountBD.multiply(interestBD).setScale(2, BigDecimal.ROUND_HALF_UP)); } while (BigDecimal.valueOf(amount).subtract(amountBD).abs().compareTo(BigDecimal.valueOf(0.01)) < 0); System.out.printf("After %,d iterations the error was 1 cent and you owe %s%n", i, amountBD);最終打印
22,473: double: $75636308370.01, BigDecimal: $75636308370.01 After 22,474 iterations the error was 1 cent and you owe 75674126524.20從IT角度來看,我們有一個錯誤的誤差,從業(yè)務(wù)角度來看,我們有一個客戶超過9年沒有還款,并且還欠銀行756億美元,足以拖垮銀行。 如果只有IT人員使用過BigDecimal !?
結(jié)論
我的最終建議是,您應(yīng)該使用自己喜歡的東西,不要忘記取整,不要使用實(shí)數(shù),而不要使用任何數(shù)學(xué)運(yùn)算法則,例如,我可以賺一分錢,還是可以交易幾分之一的份額。 不要忘記業(yè)務(wù)視角。 您可能會發(fā)現(xiàn)BigDecimal對您的公司,項(xiàng)目或團(tuán)隊(duì)更有意義。
不要以為BigDecimal是唯一的方法,不要以為雙面問題也不適用于BigDecimal。 BigDecimal并不是最佳實(shí)踐編碼的門票,因?yàn)樽詽M是引入錯誤的肯定方法。
翻譯自: https://www.javacodegeeks.com/2014/07/compounding-double-error.html
復(fù)合主鍵 復(fù)合外鍵
總結(jié)
以上是生活随笔為你收集整理的复合主键 复合外键_复合双重错误的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 服务器如何防御ddos(服务器ddos防
- 下一篇: 住建云备案流程(住建云备案)