Java/Data Type/BigDecimal

Материал из Java эксперт
Версия от 06:32, 1 июня 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Calculation with BigDecimal

    
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
public class BigDecimalInvoiceApp {
  public static void main(String[] args) {
    double subtotal = 123.123;
    double discountPercent = 0.2;
    BigDecimal decimalSubtotal = new BigDecimal(Double.toString(subtotal));
    decimalSubtotal = decimalSubtotal.setScale(2, RoundingMode.HALF_UP);
    BigDecimal decimalDiscountPercent = new BigDecimal(Double.toString(discountPercent));
    BigDecimal discountAmount = decimalSubtotal.multiply(decimalDiscountPercent);
    discountAmount = discountAmount.setScale(2, RoundingMode.HALF_UP);
    BigDecimal totalBeforeTax = decimalSubtotal.subtract(discountAmount);
    BigDecimal salesTaxPercent = new BigDecimal(".05");
    BigDecimal salesTax = salesTaxPercent.multiply(totalBeforeTax);
    salesTax = salesTax.setScale(2, RoundingMode.HALF_UP);
    BigDecimal total = totalBeforeTax.add(salesTax);
    NumberFormat currency = NumberFormat.getCurrencyInstance();
    NumberFormat percent = NumberFormat.getPercentInstance();
    String message = "Subtotal:         " + currency.format(decimalSubtotal) + "\n"
        + "Discount percent: " + percent.format(decimalDiscountPercent) + "\n"
        + "Discount amount:  " + currency.format(discountAmount) + "\n" + "Total before tax: "
        + currency.format(totalBeforeTax) + "\n" + "Sales tax:        " + currency.format(salesTax)
        + "\n" + "Invoice total:    " + currency.format(total) + "\n";
    System.out.println(message);
  }
}
/*Subtotal:         $123.12
Discount percent: 20%
Discount amount:  $24.62
Total before tax: $98.50
Sales tax:        $4.93
Invoice total:    $103.43
*/





Convert Object to BigDecimal

   

import java.math.BigDecimal;
import java.math.BigInteger;
/**
 * Utility methods for math classes
 * 
 * @author etirelli
 */
public class MathUtils {
    
    public static BigDecimal getBigDecimal( Object value ) {
        BigDecimal ret = null;
        if( value != null ) {
            if( value instanceof BigDecimal ) {
                ret = (BigDecimal) value;
            } else if( value instanceof String ) {
                ret = new BigDecimal( (String) value );
            } else if( value instanceof BigInteger ) {
                ret = new BigDecimal( (BigInteger) value );
            } else if( value instanceof Number ) {
                ret = new BigDecimal( ((Number)value).doubleValue() );
            } else {
                throw new ClassCastException("Not possible to coerce ["+value+"] from class "+value.getClass()+" into a BigDecimal.");
            }
        }
        return ret;
    }

}





Create a BigDecimal vis string

    
import java.math.BigDecimal;
public class Main {
  public static void main(String[] argv) throws Exception {
    // Create via a string
    BigDecimal bd1 = new BigDecimal("123456789.0123456890");
    // Create via a long
    BigDecimal bd2 = BigDecimal.valueOf(123L);
    bd1 = bd1.add(bd2);
  }
}





Create Big Decimal Values via a long

    
import java.math.BigDecimal;
public class Main {
  public static void main(String[] argv) throws Exception {
    // Create via a string
    BigDecimal bd1 = new BigDecimal("123456789.0123456890");
    // Create via a long
    BigDecimal bd2 = BigDecimal.valueOf(123L);
    bd1 = bd1.add(bd2);
  }
}





Create Big Decimal Values via a string

    
import java.math.BigDecimal;
public class Main {
  public static void main(String[] argv) throws Exception {
    // Create via a string
    BigDecimal bd1 = new BigDecimal("123456789.0123456890");
    // Create via a long
    BigDecimal bd2 = BigDecimal.valueOf(123L);
    bd1 = bd1.add(bd2);
  }
}





Divide one BigDecimal from another BigDecimal

    
import java.math.BigDecimal;
public class Main {
  public static void main(String[] argv) throws Exception {
    BigDecimal bd1 = new BigDecimal("123456789.0123456890");
    // Create via a long
    BigDecimal bd2 = BigDecimal.valueOf(123L);
    bd1 = bd1.divide(bd2, BigDecimal.ROUND_UP);
  }
}





Do math operation for BigDecimal

    
import java.math.BigDecimal;
public class Main {
  public static void main(String[] args) {
    BigDecimal decimalA = new BigDecimal("123456789012345");
    BigDecimal decimalB = new BigDecimal("10");
    decimalA = decimalA.add(decimalB);
    System.out.println("decimalA = " + decimalA);
    decimalA = decimalA.multiply(decimalB);
    System.out.println("decimalA = " + decimalA);
    decimalA = decimalA.subtract(decimalB);
    System.out.println("decimalA = " + decimalA);
    decimalA = decimalA.divide(decimalB);
    System.out.println("decimalA = " + decimalA);
    decimalA = decimalA.pow(2);
    System.out.println("decimalA = " + decimalA);
    decimalA = decimalA.negate();
    System.out.println("decimalA = " + decimalA);
  }
}





Formats BigDecimal into a SQL floating-point literal

   
/**********************************************************************
Copyright (c) 2002 Mike Martin (TJDO) and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 
Contributors:
2002 Kelly Grizzle (TJDO)
2003 Andy Jefferson - coding standards
    ...
**********************************************************************/

import java.math.BigDecimal;
/**
 * Utility class providing SQL formatting methods.
 *
 * @version $Revision: 1.2 $
 **/
public class SQLFormat
{
    /**
     * Formats the given BigDecimal value into a SQL floating-point literal.
     * BigDecimal.toString() is not well suited to this purpose because it never
     * uses E-notation, which causes some values with large exponents to be
     * output as long strings with tons of zeroes in them.
     *
     * @param bd  The number to format.
     *
     * @return  The formatted String.
     */
    public static String format(BigDecimal bd)
    {
        String digits = bd.unscaledValue().abs().toString();
        int scale = bd.scale();
        int len = digits.length();
        /* Normalize by removing any trailing zeroes. */
        while (len > 1 && digits.charAt(len - 1) == "0")
        {
            --scale;
            --len;
        }
        if (len < digits.length())
        {
            digits = digits.substring(0, len);
        }
        StringBuffer sb = new StringBuffer();
        if (bd.signum() < 0)
        {
            sb.append("-");
        }
        int exponent = len - scale;
        if (exponent < 0 || exponent > len)
        {
            /* Output in E-notation. */
            sb.append(".").append(digits).append("E").append(exponent);
        }
        else if (exponent == len)
        {
            /* Output as an integer. */
            sb.append(digits);
        }
        else
        {
            /* Output as "intDigits.fracDigits". */
            sb.append(digits.substring(0, exponent)).append(".").append(digits.substring(exponent));
        }
        return sb.toString();
    }
}
/////////////////////////////////////////
/*
 * The terms of the JPOX License are distributed with the software documentation.
 */
package org.jpox.util;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Random;
import org.jpox.util.SQLFormat;
import junit.framework.TestCase;

/**
 * Tests the functionality of {@link SQLFormat}.
 * 
 * @author 
 * 
 */
public class SQLFormatTest extends TestCase
{
    /**
     * Used by the JUnit framework to construct tests.  Normally, programmers
     * would never explicitly use this constructor.
     *
     * @param name   Name of the <tt>TestCase</tt>.
     */
    public SQLFormatTest(String name)
    {
        super(name);
    }

    private static final String[][] CUSTOM_CASES =
    {
        { "0",          "0" },
        { "12.34",      "12.34" },
        { "1.234",      "1234e-3" },
        { ".1234E12",   "123400000000" },
        { "-.1234",     "-1234e-4" },
        { "1234",       ".1234e+4" },
        { ".75E10",     ".75e+10" },
        { "-.75E10",    "-7.5e+9" },
        { ".5E-9",      "5e-10" }
    };
    public void testCustomValues() throws Throwable
    {
        for (int i = 0; i < CUSTOM_CASES.length; ++i)
            assertEquals(CUSTOM_CASES[i][0], SQLFormat.format(new BigDecimal(CUSTOM_CASES[i][1])));
    }

    private static final int NUM_RANDOM_CASES = 5000;
    public void testRandomValues() throws Throwable
    {
        Random rnd = new Random(0L);
        for (int i = 0; i < NUM_RANDOM_CASES; ++i)
        {
            BigDecimal bd1 = new BigDecimal(new BigInteger(128, rnd), rnd.nextInt(100));
            String s = SQLFormat.format(bd1);
            BigDecimal bd2 = new BigDecimal(SQLFormat.format(bd1));
            assertEquals("Formatting " + bd1 + " yielded " + s + " which doesn"t equal", 0, bd1.rupareTo(bd2));
        }
    }
}





Multiply one BigDecimal to another BigDecimal

    
import java.math.BigDecimal;
public class Main {
  public static void main(String[] argv) throws Exception {
    BigDecimal bd1 = new BigDecimal("123456789.0123456890");
    // Create via a long
    BigDecimal bd2 = BigDecimal.valueOf(123L);
    bd1 = bd1.multiply(bd2);
  }
}





Negate a BigDecimal

    
import java.math.BigDecimal;
public class Main {
  public static void main(String[] argv) throws Exception {
    BigDecimal bd1 = new BigDecimal("123456789.0123456890");
    bd1 = bd1.negate();
  }
}





Operate with big decimal values

    
import java.math.BigDecimal;
public class Main {
  public static void main(String[] argv) throws Exception {
    // Create via a string
    BigDecimal bd1 = new BigDecimal("123456789.0123456890");
    // Create via a long
    BigDecimal bd2 = BigDecimal.valueOf(123L);
    bd1 = bd1.add(bd2);
    bd1 = bd1.multiply(bd2);
    bd1 = bd1.subtract(bd2);
    bd1 = bd1.divide(bd2, BigDecimal.ROUND_UP);
    bd1 = bd1.negate();
  }
}





Parse BigDecimal

   
/*
 * This file is part of JGAP.
 *
 * JGAP offers a dual license model containing the LGPL as well as the MPL.
 *
 * For licensing information please see the file license.txt included with JGAP
 * or have a look at the top of class org.jgap.Chromosome which representatively
 * includes the JGAP license policy applicable for any file delivered with JGAP.
 */

/**
 * Utility routines related to numbers.
 *
 * @author Klaus Meffert
 * @since 3.2
 */
public class NumberKit {

  /**
   * Returns the hex value of "c" or -1 if there is no corresponding hex value.
   *
   * @param a_c hex character to convert
   * @return integer value of the character
   *
   * @author unknown
   * @since 3.2
   */
  public static int hexValue(char a_c) {
    if ("0" <= a_c && a_c <= "9") {
      return a_c - "0";
    }
    if ("A" <= a_c && a_c <= "F") {
      return a_c - "A" + 10;
    }
    if ("a" <= a_c && a_c <= "f") {
      return a_c - "a" + 10;
    }
    return -1;
  }
  private static final char[] DIGITS = {"0", "1", "2", "3", "4", "5", "6",
      "7", "8", "9", "a", "b", "c", "d", "e", "f"};
  /**
   * Transforms a byte to a character array of hex octets.
   * Taken from UUID.
   *
   * @param a_in the byte
   * @return the hex byte array
   */
  public static char[] asChars(byte a_in) {
    return asChars(a_in, 2);
  }
  /**
   * Transforms a byte to a character array of hex octets.
   * Taken from UUID.
   *
   * @param a_in the byte
   * @param a_length the number of octets to produce
   * @return the hex byte array
   */
  public static char[] asChars(byte a_in, int a_length) {
    char[] out = new char[a_length--];
    for (int i = a_length; i > -1; i--) {
      out[i] = DIGITS[ (byte) (a_in & 0x0F)];
      a_in >>= 4;
    }
    return out;
  }
  /**
   * Parses a short from a hex encoded number. This method will skip
   * all characters that are not 0-9 and a-f (the String is lower cased first).
   *
   * @param s the String to extract a short from, may not be null
   * @return 0 if the String does not contain any interesting characters
   * @throws NullPointerException if the String is null
   *
   * @since 3.3.3
   */
  public static short parseShort(String s)
      throws NullPointerException {
    s = s.toLowerCase();
    short out = 0;
    byte shifts = 0;
    char c;
    for (int i = 0; i < s.length() && shifts < 4; i++) {
      c = s.charAt(i);
      if ( (c > 47) && (c < 58)) {
        out <<= 4;
        ++shifts;
        out |= c - 48;
      }
      else if ( (c > 96) && (c < 103)) {
        ++shifts;
        out <<= 4;
        out |= c - 87;
      }
    }
    return out;
  }
  /**
   * Formats a number as a string having the total length of a_places, filling
   * up needed characters with a_filler.
   *
   * @param a_number the number to format
   * @param a_places total length of output string
   * @param a_filler fill character
   * @return formatted number
   *
   * @author Klaus Meffert
   * @since 3.3.3
   */
  public static String niceNumber(int a_number, int a_places, char a_filler) {
    String s = a_number + "";
    while (s.length() < a_places) {
      s = a_filler + s;
    }
    return s;
  }
  /**
   * Removes decimal places if there are more than a_decimals.
   *
   * @param a_number the number to convert to a string
   * @param a_decimals maximum number of decimal places allowed
   *
   * @return nicified string
   *
   * @author Klaus Meffert
   * @since 3.3.3
   */
  public static String niceDecimalNumber(double a_number, int a_decimals) {
    String s = a_number + "";
    int index = s.indexOf(".");
    if (index > 0) {
      // Do not remove anything if "E" is contained in the number string.
      // ----------------------------------------------------------------
      if (s.indexOf("E",index) > 0) {
        return s;
      }
      if (index + a_decimals >= s.length()) {
        a_decimals = s.length() - index - 1;
      }
      s = s.substring(0, index + a_decimals + 1);
      if (s.lastIndexOf(".") == s.length() - 1) {
        if (a_decimals < 1) {
          s = s.substring(0, s.length() - 1);
        }
        else {
          for (int i = 0; i < a_decimals; i++) {
            s += "0";
          }
        }
      }
    }
    return s;
  }
}





Round a double

    
import java.math.BigDecimal;
public class Main {
  public static void main(String args[]) {
    BigDecimal bd = new BigDecimal(3.14159);
    bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
    System.out.println(bd);
  }
}
//3.14





Round a double by setting the scale

    
import java.math.BigDecimal;
public class Main {
  public static void main(String args[]) {
    double r = 3.1234567;
    int decimalPlace = 2;
    BigDecimal bd = new BigDecimal(r);
    bd = bd.setScale(decimalPlace, BigDecimal.ROUND_UP);
    r = bd.doubleValue();
    System.out.println(r);
  }
}





Round the given value to the specified number of decimal places. The value is rounded using the BigDecimal.ROUND_HALF_UP method.

  
import java.math.BigDecimal;
/* 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *
 */
public class Main {
  /**
   * Round the given value to the specified number of decimal places. The
   * value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method.
   * 
   * @param x the value to round.
   * @param scale the number of digits to the right of the decimal point.
   * @return the rounded value.
   * @since 1.1
   */
  public static double round(double x, int scale) {
      return round(x, scale, BigDecimal.ROUND_HALF_UP);
  }
  /**
   * Round the given value to the specified number of decimal places. The
   * value is rounded using the given method which is any method defined in
   * {@link BigDecimal}.
   * 
   * @param x the value to round.
   * @param scale the number of digits to the right of the decimal point.
   * @param roundingMethod the rounding method as defined in
   *        {@link BigDecimal}.
   * @return the rounded value.
   * @since 1.1
   */
  public static double round(double x, int scale, int roundingMethod) {
      try {
          return (new BigDecimal
                 (Double.toString(x))
                 .setScale(scale, roundingMethod))
                 .doubleValue();
      } catch (NumberFormatException ex) {
          if (Double.isInfinite(x)) {
              return x;          
          } else {
              return Double.NaN;
          }
      }
  }
}





Setting the Decimal Place of a Big Decimal Value

    

import java.math.BigDecimal;
public class Main {
  public static void main(String[] argv) throws Exception {
    int decimalPlaces = 2;
    BigDecimal bd = new BigDecimal("123456789.0123456890");
     
    bd = bd.setScale(decimalPlaces, BigDecimal.ROUND_DOWN);
    String string = bd.toString();
  }
}





Subtract from one BigDecimal another BigDecimal

    
import java.math.BigDecimal;
public class Main {
  public static void main(String[] argv) throws Exception {
    BigDecimal bd1 = new BigDecimal("123456789.0123456890");
    // Create via a long
    BigDecimal bd2 = BigDecimal.valueOf(123L);
    bd1 = bd1.subtract(bd2);
  }
}





Truncates the big decimal value

    
import java.math.BigDecimal;
public class Main {
  public static void main(String[] argv) throws Exception {
    int decimalPlaces = 2;
    BigDecimal bd = new BigDecimal("123456789.0123456890");
     
    bd = bd.setScale(decimalPlaces, BigDecimal.ROUND_DOWN);
    String string = bd.toString();
  }
}





Value is rounded using the given method which is any method defined in BigDecimal

  
import java.math.BigDecimal;
/* 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *
 */
public class Main {

  /**
   * Round the given value to the specified number of decimal places. The
   * value is rounded using the given method which is any method defined in
   * {@link BigDecimal}.
   * 
   * @param x the value to round.
   * @param scale the number of digits to the right of the decimal point.
   * @param roundingMethod the rounding method as defined in
   *        {@link BigDecimal}.
   * @return the rounded value.
   * @since 1.1
   */
  public static double round(double x, int scale, int roundingMethod) {
      try {
          return (new BigDecimal
                 (Double.toString(x))
                 .setScale(scale, roundingMethod))
                 .doubleValue();
      } catch (NumberFormatException ex) {
          if (Double.isInfinite(x)) {
              return x;          
          } else {
              return Double.NaN;
          }
      }
  }
}