我的应用程序需要小数乘以货币值。
例如,65.50 美元 × 0.55 小时 = 36.025 美元
(四舍五入为 36.03 美元
)。
我知道 float 不应该用来表示金钱,所以我将我所有的货币值(value)存储为美分。上述等式中的 $65.50
存储为 6550
(整数)。
对于小数系数,我的问题是 0.55
没有 32 位浮点表示。在上面的用例中,0.55 小时 == 33 分钟
,因此 0.55
是我的应用程序需要准确考虑的特定值的示例。 0.550000012
的浮点表示是不够的,因为用户不会理解额外的0.000000012
是从哪里来的。我不能简单地对 0.550000012
调用舍入函数,因为它会舍入到整数。
乘法解
为了解决这个问题,我的第一个想法是将所有数量存储为整数并乘以 × 1000。因此用户输入的 0.55
在存储时将变为 550
(整数) .所有计算都将在没有 float 的情况下进行,然后在向用户显示结果时简单地除以 1000(整数除法,而不是 float )。
我意识到这将永久限制我的小数点后 3 位 精确。如果我决定 3 对我的一生来说足够了 应用,这种做法有意义吗?
如果我使用整数除法,是否存在潜在的舍入问题?
这个过程有名称吗? 编辑:如@SergGr 所示,这是 fixed-point arithmetic .
有没有更好的方法?
编辑:
我应该澄清一下,这不是特定时间的。它适用于一般数量,例如 1.256 磅面粉
、1 沙发
或 0.25 小时
(想想发票)。
我在这里尝试复制的是 Postgres 的 extra_float_digits = 0
功能的更精确版本,如果用户输入 0.55
(float32),数据库存储0.550000012
但当查询结果时返回 0.55
这似乎正是用户键入的内容。
我愿意将此应用程序的精度限制在小数点后 3 位(这是业务,而不是科学),所以这就是让我考虑 × 的原因。 1000
方法。
我正在使用 Go 编程语言,但我对通用的跨语言解决方案很感兴趣。
最佳答案
存储结果的另一种解决方案是使用值的有理形式。你可以用等于p/q
的两个整数值来解释这个数字,这样p
和q
都是整数。因此,您可以更精确地计算数字,并以两个整数的格式对有理数进行一些数学运算。
关于go - 使用整数作为小数系数而不是 float 对于货币应用来说是个好主意吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54067997/