Why we don’t use Doubles for Financial Calculations

原文地址:http://bloodredsun.com/?p=320
另一篇文章:What Every Computer Scientist Should Know About Floating-Point Arithmetichttp://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html


My current client is in the middle of hiring some Java developers and as I
mentioned earlier in March (Interviewing – the importance of PASSION!) I’ve been doing some of the interviewing. One of the things we’ve done is to create a technical task to see how the candidates actually code. It’s a simple exercise that requires them to think through some of the basics of financial operations and one thing that has surprised me has been the common use of doubles to represent financial values. It’s been highlighted for some time that this is not a great thing to do but someone actually challenged me to show that it wasn’t.

So here we go…

view plaincopy to clipboardprint?
package com.bloodredsun; 
 
public class DoubleOperation { 
 
    public static void main(String[] args) { 
 
        double t1 = 10.266d; 
        double t2 = 10.0d; 
 
        //Outputs 0.266 
        System.out.println(t1-t2); 
 
        double h1 = 100.266d; 
        double h2 = 100.0d; 
 
        //Outputs 0.26600000000000534 
        System.out.println(h1-h2); 
    } 

Ouch! That is not what we want but it is the classic behaviour of doubles. The inability to represent some decimals in the IEEE-754 format (as binary fractions) causes this. If we want correct precision the answer is to use BigDecimals but we have to remember to use Strings in the constructors or you end up with the same issues that you were trying to avoid.

view plaincopy to clipboardprint?
package com.bloodredsun; 
 
import java.math.BigDecimal; 
 
public class BigDecimalOperation { 
 
        public static void main(String[] args) { 
 
        BigDecimal t1 = new BigDecimal("10.266"); 
        BigDecimal t2 = new BigDecimal("10.0"); 
 
        //Outputs 0.266 
        System.out.println(t1.subtract(t2)); 
 
        BigDecimal h1 = new BigDecimal("100.266"); 
        BigDecimal h2 = new BigDecimal("100.0"); 
 
        //Outputs 0.266 
        System.out.println(h1.subtract(h2)); 
    } 

That’s great but wouldn’t it be nice to use the normal operators rather than the overly-verbose method calls for the mathematical operations.

Now there is no way that we can do this in Java but if we let ourselves use another language on the JVM…

view plaincopy to clipboardprint?
package com.bloodredsun 
 
object ScalaBigDecimalOperation { 
 
  def main (args: Array[String]) { 
    var t1 = BigDecimal("10.266") 
    var t2 = BigDecimal("10.0") 
    //Outputs 0.266 
    println(t1 - t2) 
 
    var h1 = BigDecimal("100.266") 
    var h2 = BigDecimal("100.0") 
    //Outputs 0.266 
    println(h1 - h2) 
  } 

Scala FTW!

PS if you want to know more about floating point operations have a read of What Every Computer Scientist Should Know About Floating-Point Arithmetic

你可能感兴趣的:(jvm,oracle,scala,UP,Go)