首页 > 图灵资讯 > 技术篇>正文
如果需要准确答案,请避免浮动和双精度
2024-10-14 13:14:10
浮动和双精度问题:
- 专为科学和数学计算而设计,执行二进制浮点运算。
- 不适合货币计算或需要精确答案的情况。
- 它们无法准确表示 10 的负幂,例如 0.1,这会导致错误。
示例1: 减去美元金额时计算错误:
system.out.println(1.03 - 0.42); // resultado: 0.6100000000000001
示例2: 以每件 10 美分的价格购买 9 件商品时出错:
system.out.println(1.00 - 9 * 0.10); // resultado: 0.09999999999999998
即使四舍五入,错误仍然存在。 累进计算存在问题,例如以 0.10 到 1.00 的增量价格购买糖果时。
示例 3: 没钱买糖果时犯的错误:
double funds = 1.00; for (double price = 0.10; funds >= price; price += 0.10) { funds -= price; } system.out.println(funds); // resultado: 0.3999999999999999
解决方案 1:使用 bigdecimal
- 非常适合财务计算和需要精确度的情况。
- 避免使用 bigdecimal 的双构造函数,最好使用 string 构造函数。
bigdecimal 示例:
bigdecimal funds = new bigdecimal("1.00"); bigdecimal price = new bigdecimal("0.10"); int itemsbought = 0; while (funds.compareto(price) >= 0) { funds = funds.subtract(price); price = price.add(new bigdecimal("0.10")); itemsbought++; } system.out.println(itemsbought + " items bought. money left: " + funds); // resultado: 4 items bought. money left: 0.00
计算现在很精确。
bigdecimal 的缺点:
- 使用起来不如原始类型方便。
- 速度较慢,尤其是对于大量操作。
解决方案 2:使用 int 或 long
- 为了避免准确性问题,请以美分为单位进行计算,使用 int 或 long 而不是使用 double 的美元。
int 示例(以分为单位):
int funds = 100; // 1.00 dólar = 100 centavos int price = 10; // 0.10 dólar = 10 centavos int itemsBought = 0; while (funds >= price) { funds -= price; price += 10; itemsBought++; } System.out.println(itemsBought + " items bought. Money left: " + funds); // Resultado: 4 items bought. Money left: 0
计算又快又准。
结论:
- 不要使用 float 或 double 进行需要精确精度的计算。
- 使用 bigdecimal 进行货币计算或需要小数精度的情况。
- 使用 int 或 long 进行不涉及大数的金融计算,以分为单位进行计算。
选择:
- 对于最多 9 位数字,请使用 int。
- 对于最多 18 位数字,请使用 long。
- 对于较大数量,请使用 bigdecimal。
- 此摘要表明,根据上下文,在 bigdecimal、int 或 long 之间进行选择可以优化精度和性能。
以上就是如果需要准确答案,请避免浮动和双精度的详细内容,更多请关注图灵教育其它相关文章!