如何在不使用双打的情况下使用 BigDecimals

How to use BigDecimals without using doubles

我正在尝试制作这个程序,让您可以购买一些不同的物品。

我将我的价格存储在一个 sqlite 数据库中(除了它是字符串或整数之外,还没有决定数据类型)。

我已经阅读了 2 个小时,现在试图掌握这一点,我明白为什么我不能使用双精度值或浮点值。

但我无法决定:我应该将我的价格存储为整数吗?或字符串。

我在这里看到的问题是,我总是被告知不要将整数存储为字符串.. 现在人们告诉我这很聪明,因为这是我保持价格准确性的唯一方法?

如果我将它们存储为整数,我将遇到以下问题:

int 5 / 100 //i want that to be 0.05
int 50 / 100 //i want that to be 0.50
int 500 / 100 //i want that to be 5.00

我如何在不使用双打的情况下做到这一点??

或者也许有一种使用 BigDecimals 的方法?

BigDecimal bddd1 = bdd1.setScale(2,RoundingMode.HALF_EVEN); // gives me 5.00 instead of 0.05

那么我将如何正确地做到这一点,总是得到 2 位小数。

将其存储为整数并存储美分。您永远不应将任何货币价值存储为任何类型的浮动价值。

所以 0.5$ 应该存储为 50 美分。计算美分而不是美元。如果您将它存储在任何浮点值中,您只是在稍后遇到所有舍入问题。

正如其他人所建议的那样,您可以使用整数来存储美分的数量,但是如果您必须计算百分比或将(美分)的数量除以 12 个月,那么您可能会遇到问题。那么你可能需要一个更准确的中间体。

BigDecimals 提供了这一切。在内部,它们是按比例缩放的整数,因此它们提供您需要的一切。

存储5美分很简单,用一个字符串初始化:

BigDecimal fiveCents = new BigDecimal("0.05");

或者,计算:

BigDecimal oneCent = new BigDecimal("0.01");
BigDecimal fiveCents = BigDecimal.valueOf(5).multiply(oneCent);

BigDecimal fiveCents = BigDecimal.valueOf(5).movePointLeft(2);

或者任何你喜欢的,只要发挥你的想象力。但是不要使用双精度数或浮点数来初始化 BigDecimals,因为当它们有小数部分时它们可能不准确。使用字符串或使用整数除以100,或乘以百分之一或小数点左移2

我看到有人认为使用 BigDecimals 表示货币值是错误的,并且您宁愿使用(缩放的)整数,但 BigDecimals 恰恰是:缩放的整数。对于 "small" 数字(低于最大 long 值),BigDecimals 甚至使用 long 而不是 BigInteger 来表示未缩放的值。

不要过早四舍五入,除非某些计算规则要求这样做。否则,只在最后舍入(setScale())。