为什么不使用 Double 或 Float 来表示货币? [英] Why not use Double or Float to represent currency?

查看:30
本文介绍了为什么不使用 Double 或 Float 来表示货币?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直被告知 从不doublefloat 类型表示货币,这次我向您提出问题:为什么?

I've always been told never to represent money with double or float types, and this time I pose the question to you: why?

我确信有一个很好的理由,我只是不知道它是什么.

I'm sure there is a very good reason, I simply do not know what it is.

推荐答案

因为浮点数和双精度数不能准确地表示我们用于货币的基数 10 倍数.这个问题不仅仅针对 Java,还针对任何使用基数 2 浮点类型的编程语言.

Because floats and doubles cannot accurately represent the base 10 multiples that we use for money. This issue isn't just for Java, it's for any programming language that uses base 2 floating-point types.

以 10 为底,您可以将 10.25 写为 1025 * 10-2(整数乘以 10 的幂).IEEE-754 浮点数 是不同的,但考虑它们的一个非常简单的方法是而是乘以 2 的幂.例如,您可以查看 164 * 2-4(整数乘以 2 的幂),它也等于 10.25.这不是数字在内存中的表示方式,但数学含义是相同的.

In base 10, you can write 10.25 as 1025 * 10-2 (an integer times a power of 10). IEEE-754 floating-point numbers are different, but a very simple way to think about them is to multiply by a power of two instead. For instance, you could be looking at 164 * 2-4 (an integer times a power of two), which is also equal to 10.25. That's not how the numbers are represented in memory, but the math implications are the same.

即使以 10 为底,这种表示法也不能准确地表示大多数简单分数.例如,你不能表示 1/3:十进制表示是重复的 (0.3333...),所以没有有限的整数可以乘以 10 的幂得到 1/3.您可以确定一长串 3 和一个小指数,例如 333333333 * 10-10,但这并不准确:如果将其乘以 3,则不会得到 1.

Even in base 10, this notation cannot accurately represent most simple fractions. For instance, you can't represent 1/3: the decimal representation is repeating (0.3333...), so there is no finite integer that you can multiply by a power of 10 to get 1/3. You could settle on a long sequence of 3's and a small exponent, like 333333333 * 10-10, but it is not accurate: if you multiply that by 3, you won't get 1.

然而,为了数钱,至少对于货币价值在美元数量级以内的国家,通常你只需要能够存储10的倍数-2,所以 1/3 不能表示也没关系.

However, for the purpose of counting money, at least for countries whose money is valued within an order of magnitude of the US dollar, usually all you need is to be able to store multiples of 10-2, so it doesn't really matter that 1/3 can't be represented.

浮点数和双精度数的问题在于,绝大多数类似货币的数字没有整数乘以 2 的幂的精确表示.事实上,只有 0.01 的倍数可以精确表示为 IEEE-754 二进制浮点数的 0 和 1 之间(在处理货币时很重要,因为它们是整数美分)是 0、0.25、0.5、0.75 和 1.所有其他都关闭少量.与 0.333333 示例类似,如果将浮点值设为 0.01,然后将其乘以 10,则不会得到 0.1.相反,你会得到类似 0.099999999786...

The problem with floats and doubles is that the vast majority of money-like numbers don't have an exact representation as an integer times a power of 2. In fact, the only multiples of 0.01 between 0 and 1 (which are significant when dealing with money because they're integer cents) that can be represented exactly as an IEEE-754 binary floating-point number are 0, 0.25, 0.5, 0.75 and 1. All the others are off by a small amount. As an analogy to the 0.333333 example, if you take the floating-point value for 0.01 and you multiply it by 10, you won't get 0.1. Instead you will get something like 0.099999999786...

将钱表示为 doublefloat 一开始可能看起来不错,因为软件会消除微小的错误,但随着您执行更多的加法、减法、乘法和在不精确的数字上进行除法,错误会复杂化,您最终会得到明显不准确的值.这使得浮点数和双精度数不适用于处理金钱,在这种情况下需要以 10 为底的幂的倍数的完美精度.

Representing money as a double or float will probably look good at first as the software rounds off the tiny errors, but as you perform more additions, subtractions, multiplications and divisions on inexact numbers, errors will compound and you'll end up with values that are visibly not accurate. This makes floats and doubles inadequate for dealing with money, where perfect accuracy for multiples of base 10 powers is required.

几乎适用于任何语言的解决方案是改用整数并计算美分.例如,1025 将是 10.25 美元.几种语言也有处理金钱的内置类型.其中,Java 有 BigDecimal 类,而 C# 具有 decimal 输入.

A solution that works in just about any language is to use integers instead, and count cents. For instance, 1025 would be $10.25. Several languages also have built-in types to deal with money. Among others, Java has the BigDecimal class, and C# has the decimal type.

这篇关于为什么不使用 Double 或 Float 来表示货币?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆