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

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

问题描述

我永远不会用 double float 类型,这次我向你提问:为什么?

我确信有一个很好的理由,我根本不知道它是什么。

解决方案

由于浮动和双打不能准确地表示我们用于金钱的基数的10倍。这个问题不仅仅针对Java,它适用于任何使用本机浮点类型的编程语言,因为它源于计算机默认处理浮点数的方式。



这是一个 IEEE-754 浮点数的工作方式:它为标志,为基数存储一些指数,其余的为高基数的倍数。这导致像10.25这样的数字以类似于1025 * 10-2的形式表示。除了基数是10以外,对于 float s和 double s来说,这是两个,所以这将是164 * 2 -4 。 (这还不完全如何在硬件中表示,但这很简单,数学也是一样。)

即使在基数为10的情况下,这种表示法也不能准确代表最简单的分数。例如,对于大多数计算器来说,1/3会导致0.333333333333的重复,因为数字显示允许有3个,因为您不能用十进制表示1/3。然而,为了钱的目的(至少对于货币价值在美元数量级以内的国家),在大多数情况下,所有你需要的是能够存储10 -2 ,所以我们并不关心1/3是否具有10次幂的整数倍的精确表示,即使是最便宜的计算器也只能处理分数。



浮动和双打的问题是,大多数类似金钱的数字没有一个整数乘二的幂的精确表示。实际上,0/100和100/100之间的百分之几(这对于处理货币是重要的,因为它们是整数美分),可以精确地表示为一个IEEE-754二进制浮点数,它们是0, 0.25,0.5,0.75和1.所有其他的都是少量的。

代表货币为 double 或者 float 可能会看起来不错,因为软件会消除这些小错误,但是当您对不精确数字执行更多的加法,减法,乘法和除法时,随着误差加起来,失去越来越多的精度。这使浮动和双打不足以处理金钱,在这种情况下,要求基数为10的倍数的完美准确性。

几乎适用于任何语言的解决方案是使用整数,而数数。例如,1025将是10.25美元。几种语言也有内置类型来处理金钱。其中,Java有 BigDecimal 类,而C#的 decimal 类型。


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.

解决方案

Because floats and doubles cannot accurately represent the base 10 multiples we use for money. This issue isn't just for Java, it's for any programming language that uses native floating-point types, as it stems from how computers handle floating-point numbers by default.

This is how an IEEE-754 floating-point number works: it dedicates a bit for the sign, a few bits to store an exponent for the base, and the rest for a multiple of that elevated base. This leads to numbers like 10.25 being represented in a form similar to 1025 * 10-2; except that instead of the base being 10, for floats and doubles, it's two, so that would be 164 * 2-4. (That's still not exactly how they are represented in hardware, but this is simple enough and the math holds the same way.)

Even in base 10, this notation cannot accurately represent most simple fractions. For instance, with most calculators, 1/3 results in a repeating 0.333333333333, with as many 3's as the digital display allows, because you just can't write 1/3 in decimal notation. However, for the purpose of money (at least for countries whose money value is within an order of magnitude of the US dollar), in most scenarios all you need is to be able to store multiples of 10-2, so we don't really care if 1/3 doesn't have an exact representation as an integer times a power of 10, and even the cheapest calculators handle cents just fine.

The problem with floats and doubles is that the vast majority of money-like numbers don't have an exact representation as a integer times a power of two. In fact, the only fractions of a hundred between 0/100 and 100/100 (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.

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, you'll lose more and more precision as the errors add up. This makes floats and doubles inadequate for dealing with money, where perfect accuracy for multiples of base 10 powers is required.

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天全站免登陆