Which type to save percentages
Is it appropriate to use the double
开发者_运维知识库type to store percentage values (for example a discount percentage in a shop application) or would it be better to use the decimal
type?
Floating-point types (float
and double
are particularly ill-suited to financial applications.
Financial calculations are almost always decimal, while floating-point types are almost always binary. Many common values that are easy to represent in decimal are impossible to represent in binary. For example, 0.2d
= 0.00110011...b
. See http://en.wikipedia.org/wiki/Binary_numeral_system#Fractions_in_binary for a good discussion.
It's also worth talking about how you're representing prices in your system. decimal
is a good choice, but floating point is not, for reasons listed above. Because you believe in Object Oriented Programming, you're going to wrap that decimal
in a new Money
type, right? A nice treatment of money comes in Kent Beck's Test Driven Development by Example.
Perhaps you will consider representing percentages as an integer, and then dividing by 100 every time you use it. However, you are setting yourself up for bugs (oops, I forgot to divide) and future inflexibility (customer wants 1/10ths of a percent, so go fix every /100
to be /1000
. Oops, missed one - bug.)
That leaves you with two good options, depending on your needs. One is decimal
. It's great for whole percentages like 10%
, but not for things like "1/3rd off today only!", as 1/3 doesn't represent exactly in decimal. You'd like it if buying 3 of something at 1/3rd off comes out as a whole number, right?
Another is to use a Fraction
type, which stores an integer
numerator and denominator. This allows you to represent exact values for all rational numbers. Either implement your own Fraction
type or pick one up from a library (search the internet).
You can probably get away with saving the discount percentage as an integer. Just store 10 or 25 or whatever, and when you need to work out the price of something:
newprice = price * discount / 100
decimal
does come at a performance cost, but it's usually worth it for financial uses. The reason it has low performance (the worst of all numeric types) is that it doesn't map directly to a hardware type. That means it requires more of the work to be done in software.
Note that it is not only an issue of size. decimal
is an integer scaled by a power of 10, while the float and double types are scaled by powers of 2. That means terminating decimal values like 0.1 can be exactly represented using decimal
, while they are non-terminating (and thus rounded) for float
and double
.
I try to avoid floating-point whenever possible. Nothing irritates me more than having .25 not equal to .25, something that happens when you start dealing with them.
A regular float should be fine, unless you need accuracy to like, five decimal places.
精彩评论