精华内容
下载资源
问答
  • 主要为大家详细介绍了java精度计算代码,java指定精确小数位,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • java.math.BigDecimal概述Javajava.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和...

    java.math.BigDecimal

    概述

    Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。

    双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中.

    如果我们需要精确计算的结果,则必须使用BigDecimal类来操作。

    ​BigDecimal所创建的是对象,故我们不能使用传统的+、-、*、/ 等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。

    BigDecimal常用构造函数

    BigDecimal(int)

    创建一个具有参数所指定整数值的对象

    BigDecimal(double)

    创建一个具有参数所指定双精度值的对象

    BigDecimal(long)

    创建一个具有参数所指定长整数值的对象

    BigDecimal(String) 常用

    创建一个具有参数所指定以字符串表示的数值的对象

    使用示例:

    BigDecimal a =new BigDecimal(0.1);

    System.out.println("a values is:"+a);

    System.out.println("=====================");

    BigDecimal b =new BigDecimal("0.1");

    System.out.println("b values is:"+b);

    结果示例:

    a values is:0.1000000000000000055511151231257827021181583404541015625

    =====================

    b values is:0.1

    原因分析:

    1)参数类型为double的构造方法的结果有一定的不可预知性。有人可能认为在Java中写入newBigDecimal(0.1)所创建的BigDecimal正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。

    2)String 构造方法是完全可预知的:写入 newBigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言, 通常建议优先使用String构造方法。

    3)当double必须用作BigDecimal的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用Double.toString(double)方法,然后使用BigDecimal(String)构造方法,将double转换为String。要获取该结果,请使用static valueOf(double)方法。

    BigDecimal常用方法详解

    常用方法

    add(BigDecimal)

    BigDecimal对象中的值相加,返回BigDecimal对象

    subtract(BigDecimal)

    BigDecimal对象中的值相减,返回BigDecimal对象

    multiply(BigDecimal)

    BigDecimal对象中的值相乘,返回BigDecimal对象

    divide(BigDecimal)

    BigDecimal对象中的值相除,返回BigDecimal对象

    toString()

    将BigDecimal对象中的值转换成字符串

    doubleValue()

    将BigDecimal对象中的值转换成双精度数

    floatValue()

    将BigDecimal对象中的值转换成单精度数

    longValue()

    将BigDecimal对象中的值转换成长整数

    intValue()

    将BigDecimal对象中的值转换成整数

    除法特记:

    public BigDecimal divide( BigDecimal divisor, int scale, int roundingMode);

    divisor 除数, scale 精确小数位, roundingMode 舍入模式

    BigDecimal的8种舍入模式

    BigDecimal resVal = new BigDecimal("0");

    舍入方法:setScale(0,BigDecimal.ROUND_UP)第一个参数0表示舍入之后的小数位数,第二个参数表示舍入方式

    1、ROUND_UP向上取整(正负远离零的舍入模式)

    BigDecimal bdNum = new BigDecimal("23.3693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_UP);

    结果:24

    BigDecimal bdNum = new BigDecimal("-23.3693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_UP);

    结果:-24

    2、ROUND_DOWN向下取整(正负接近零的舍入模式)

    BigDecimal bdNum = new BigDecimal("23.3693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_DOWN);

    结果:23

    BigDecimal bdNum = new BigDecimal("-23.3693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_DOWN);

    结果:-23

    3、ROUND_CEILING向大取整(比原数值大的方向) 如果 BigDecimal 为正,则舍入行为与 ROUND_UP 相同; 如果为负,则舍入行为与 ROUND_DOWN 相同。

    BigDecimal bdNum = new BigDecimal("23.3693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_CEILING);

    结果:24

    BigDecimal bdNum = new BigDecimal("-23.3693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_CEILING);

    结果:-23

    4、ROUND_FLOOR向小取整(比原数值小的方向)如果 BigDecimal 为正,则舍入行为与 ROUND_DOWN 相同; 如果为负,则舍入行为与 ROUND_UP 相同。

    BigDecimal bdNum = new BigDecimal("23.3693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_FLOOR);

    结果:23

    BigDecimal bdNum = new BigDecimal("-23.3693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_FLOOR);

    结果:-24

    5、ROUND_HALF_UP(四舍五入) 向“最接近的”数字舍入,如果舍弃部分 >= 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。

    BigDecimal bdNum = new BigDecimal("23.3693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_UP);

    结果:23

    BigDecimal bdNum = new BigDecimal("23.6693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_UP);

    结果:24

    BigDecimal bdNum = new BigDecimal("23.5");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_UP);

    结果:24

    6、ROUND_HALF_DOWN(五舍六入) 向“最接近的”数字舍入,如果舍弃部分 <= 0.5,则舍入行为与 ROUND_DOWN 相同; 否则舍入行为与 ROUND_UP 相同。

    BigDecimal bdNum = new BigDecimal("23.3693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_DOWN);

    结果:23

    BigDecimal bdNum = new BigDecimal("23.6693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_DOWN);

    结果:24

    BigDecimal bdNum = new BigDecimal("23.5");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_DOWN);

    结果:23

    7、ROUND_HALF_EVEN

    向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。 如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同; 如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。

    四舍六入,五分两种情况。 如果前一位为奇数,则入位,否则舍去。

    BigDecimal bdNum = new BigDecimal("23.3693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_EVEN);

    结果:23

    BigDecimal bdNum = new BigDecimal("23.6693");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_EVEN);

    结果:24

    BigDecimal bdNum = new BigDecimal("23.5");// 如果与两个相邻数字的距离相等,则向相邻的偶数舍入

    resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_EVEN);

    结果:24

    BigDecimal bdNum = new BigDecimal("22.5");// 如果与两个相邻数字的距离相等,则向相邻的偶数舍入

    resVal = bdNum.setScale(0, BigDecimal.ROUND_HALF_EVEN);

    结果:22

    8、ROUND_UNNECESSARY 断言请求的操作具有精确的结果,因此不需要舍入。 如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。

    BigDecimal bdNum = new BigDecimal("22.3368");

    resVal = bdNum.setScale(4, BigDecimal.ROUND_UNNECESSARY);

    结果:22.3368

    BigDecimal bdNum = new BigDecimal("22.3368");

    resVal = bdNum.setScale(0, BigDecimal.ROUND_UNNECESSARY);

    结果:

    Exception in thread "main" java.lang.ArithmeticException: Rounding necessary

    at java.math.BigDecimal.commonNeedIncrement(BigDecimal.java:4148)

    at java.math.BigDecimal.needIncrement(BigDecimal.java:4204)

    at java.math.BigDecimal.divideAndRound(BigDecimal.java:4112)

    at java.math.BigDecimal.setScale(BigDecimal.java:2452)

    at com.example.demo622.Demo622ApplicationTests.main(Demo622ApplicationTests.java:213)

    BigDecimal 平方根

    BigDecimal bdNum1 = new BigDecimal(String.valueOf(Math.sqrt(4)));

    结果:2.0

    BigDecimal 幂次方

    BigDecimal res = new BigDecimal("3").pow(2); // 3的2次方

    结果: res = 9;

    BigDecimal大小比较

    java中对BigDecimal比较大小一般用的是bigdemical的compareTo方法

    BigDecimal a = new BigDecimal ("1");

    BigDecimal b = new BigDecimal ("2");

    int val = a.compareTo(b);

    System.out.println(val);

    返回结果分析:

    val = -1,表示a小于b;

    若 val = 0 ,表示a等于b;

    若 val = 1 ,表示a大于b;

    BigDecimal总结

    6.1、总结

    在需要精确的小数计算时再使用BigDecimal,BigDecimal的性能比double和float差,在处理庞大,复杂的运算时尤为明显。故一般精度的计算没必要使用BigDecimal。

    尽量使用参数类型为String的构造函数。

    BigDecimal都是不可变的(immutable)的, 在进行每一次四则运算时,都会产生一个新的对象 ,所以在做加减乘除运算时要记得要保存操作后的值。

    /**

    * BigDecimal高精度数学计算

    */

    public class ArithmeticUtils {

    //默认除法运算精度

    private static final int DEF_DIV_SCALE = 10;

    /**

    * 提供精确的加法运算

    *

    * @param v1 被加数

    * @param v2 加数

    * @return 两个参数的和

    */

    public static double add(double v1, double v2) {

    BigDecimal b1 = new BigDecimal(Double.toString(v1));

    BigDecimal b2 = new BigDecimal(Double.toString(v2));

    return b1.add(b2).doubleValue();

    }

    /**

    * 提供精确的加法运算

    *

    * @param v1 被加数

    * @param v2 加数

    * @return 两个参数的和

    */

    public static BigDecimal add(String v1, String v2) {

    BigDecimal b1 = new BigDecimal(v1);

    BigDecimal b2 = new BigDecimal(v2);

    return b1.add(b2);

    }

    /**

    * 提供精确的加法运算

    *

    * @param v1 被加数

    * @param v2 加数

    * @param scale 保留scale 位小数

    * @return 两个参数的和

    */

    public static String add(String v1, String v2, int scale) {

    if (scale < 0) {

    throw new IllegalArgumentException(

    "The scale must be a positive integer or zero");

    }

    BigDecimal b1 = new BigDecimal(v1);

    BigDecimal b2 = new BigDecimal(v2);

    return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();

    }

    /**

    * 提供精确的减法运算

    *

    * @param v1 被减数

    * @param v2 减数

    * @return 两个参数的差

    */

    public static double sub(double v1, double v2) {

    BigDecimal b1 = new BigDecimal(Double.toString(v1));

    BigDecimal b2 = new BigDecimal(Double.toString(v2));

    return b1.subtract(b2).doubleValue();

    }

    /**

    * 提供精确的减法运算。

    *

    * @param v1 被减数

    * @param v2 减数

    * @return 两个参数的差

    */

    public static BigDecimal sub(String v1, String v2) {

    BigDecimal b1 = new BigDecimal(v1);

    BigDecimal b2 = new BigDecimal(v2);

    return b1.subtract(b2);

    }

    /**

    * 提供精确的减法运算

    *

    * @param v1 被减数

    * @param v2 减数

    * @param scale 保留scale 位小数

    * @return 两个参数的差

    */

    public static String sub(String v1, String v2, int scale) {

    if (scale < 0) {

    throw new IllegalArgumentException(

    "The scale must be a positive integer or zero");

    }

    BigDecimal b1 = new BigDecimal(v1);

    BigDecimal b2 = new BigDecimal(v2);

    return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();

    }

    /**

    * 提供精确的乘法运算

    *

    * @param v1 被乘数

    * @param v2 乘数

    * @return 两个参数的积

    */

    public static double mul(double v1, double v2) {

    BigDecimal b1 = new BigDecimal(Double.toString(v1));

    BigDecimal b2 = new BigDecimal(Double.toString(v2));

    return b1.multiply(b2).doubleValue();

    }

    /**

    * 提供精确的乘法运算

    *

    * @param v1 被乘数

    * @param v2 乘数

    * @return 两个参数的积

    */

    public static BigDecimal mul(String v1, String v2) {

    BigDecimal b1 = new BigDecimal(v1);

    BigDecimal b2 = new BigDecimal(v2);

    return b1.multiply(b2);

    }

    /**

    * 提供精确的乘法运算

    *

    * @param v1 被乘数

    * @param v2 乘数

    * @param scale 保留scale 位小数

    * @return 两个参数的积

    */

    public static double mul(double v1, double v2, int scale) {

    BigDecimal b1 = new BigDecimal(Double.toString(v1));

    BigDecimal b2 = new BigDecimal(Double.toString(v2));

    return round(b1.multiply(b2).doubleValue(), scale);

    }

    /**

    * 提供精确的乘法运算

    *

    * @param v1 被乘数

    * @param v2 乘数

    * @param scale 保留scale 位小数

    * @return 两个参数的积

    */

    public static String mul(String v1, String v2, int scale) {

    if (scale < 0) {

    throw new IllegalArgumentException(

    "The scale must be a positive integer or zero");

    }

    BigDecimal b1 = new BigDecimal(v1);

    BigDecimal b2 = new BigDecimal(v2);

    return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();

    }

    /**

    * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到

    * 小数点以后10位,以后的数字四舍五入

    *

    * @param v1 被除数

    * @param v2 除数

    * @return 两个参数的商

    */

    public static double div(double v1, double v2) {

    return div(v1, v2, DEF_DIV_SCALE);

    }

    /**

    * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指

    * 定精度,以后的数字四舍五入

    *

    * @param v1 被除数

    * @param v2 除数

    * @param scale 表示表示需要精确到小数点以后几位。

    * @return 两个参数的商

    */

    public static double div(double v1, double v2, int scale) {

    if (scale < 0) {

    throw new IllegalArgumentException("The scale must be a positive integer or zero");

    }

    BigDecimal b1 = new BigDecimal(Double.toString(v1));

    BigDecimal b2 = new BigDecimal(Double.toString(v2));

    return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();

    }

    /**

    * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指

    * 定精度,以后的数字四舍五入

    *

    * @param v1 被除数

    * @param v2 除数

    * @param scale 表示需要精确到小数点以后几位

    * @return 两个参数的商

    */

    public static String div(String v1, String v2, int scale) {

    if (scale < 0) {

    throw new IllegalArgumentException("The scale must be a positive integer or zero");

    }

    BigDecimal b1 = new BigDecimal(v1);

    BigDecimal b2 = new BigDecimal(v1);

    return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();

    }

    /**

    * 提供精确的小数位四舍五入处理

    *

    * @param v 需要四舍五入的数字

    * @param scale 小数点后保留几位

    * @return 四舍五入后的结果

    */

    public static double round(double v, int scale) {

    if (scale < 0) {

    throw new IllegalArgumentException("The scale must be a positive integer or zero");

    }

    BigDecimal b = new BigDecimal(Double.toString(v));

    return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();

    }

    /**

    * 提供精确的小数位四舍五入处理

    *

    * @param v 需要四舍五入的数字

    * @param scale 小数点后保留几位

    * @return 四舍五入后的结果

    */

    public static String round(String v, int scale) {

    if (scale < 0) {

    throw new IllegalArgumentException(

    "The scale must be a positive integer or zero");

    }

    BigDecimal b = new BigDecimal(v);

    return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();

    }

    /**

    * 取余数

    *

    * @param v1 被除数

    * @param v2 除数

    * @param scale 小数点后保留几位

    * @return 余数

    */

    public static String remainder(String v1, String v2, int scale) {

    if (scale < 0) {

    throw new IllegalArgumentException(

    "The scale must be a positive integer or zero");

    }

    BigDecimal b1 = new BigDecimal(v1);

    BigDecimal b2 = new BigDecimal(v2);

    return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();

    }

    /**

    * 取余数 BigDecimal

    *

    * @param v1 被除数

    * @param v2 除数

    * @param scale 小数点后保留几位

    * @return 余数

    */

    public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {

    if (scale < 0) {

    throw new IllegalArgumentException(

    "The scale must be a positive integer or zero");

    }

    return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);

    }

    /**

    * 比较大小

    *

    * @param v1 被比较数

    * @param v2 比较数

    * @return 如果v1 大于v2 则 返回true 否则false

    */

    public static boolean compare(String v1, String v2) {

    BigDecimal b1 = new BigDecimal(v1);

    BigDecimal b2 = new BigDecimal(v2);

    int bj = b1.compareTo(b2);

    boolean res;

    if (bj > 0)

    res = true;

    else

    res = false;

    return res;

    }

    }

    展开全文
  • js在处理小数除法的时候有一个bug,解决的方法可以是:将小数变为整数来处理。 以上的计算可以改为: 12.32 * 100 * 7 /100 得出的结果是:86.24,正确。   另外再计算一下: 8.80 * 100 * 12 / 100 结果:105....
  • 大数乘法可以进行任意大小和精度的整数和浮点数的乘法运算, 精确度很高, 可以用作经融等领域的计算.这个是我看了一些资料, 然后自己整理实现的. 简单测试了一下.import java.io.BufferedReader;import java.io....

    大数乘法可以进行任意大小和精度的整数和浮点数的乘法运算, 精确度很高, 可以用作经融等领域的计算.

    这个是我看了一些资料, 然后自己整理实现的. 简单测试了一下.

    import java.io.BufferedReader;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.util.regex.Matcher;

    import java.util.regex.Pattern;

    /**

    * 大数乘法的简单实现, 目前还不是很完善

    * Fix:

    * 1. 修改前后删除0的一些错误情况

    * 2. 支持负数运算

    * 3. 判断输入字符串是否符合小数定义, 用正则表达式判断

    * @author icejoywoo

    * @since 2012.2.16

    * @version 0.1.1

    */

    public class BigNumber {

    public static void main(String[] args) throws IOException {

    System.out.println("Input two large integers:");

    BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));

    String[] strArray = buffer.readLine().split("\\*");

    System.out.println(bigNumberMultiply(strArray[0], strArray[1]));

    }

    /**

    * 计算两个任意大小和精度的数的乘积

    * @param first 第一个参数

    * @param second 第二个参数

    * @return 两个数的乘积

    */

    private static String bigNumberMultiply(String first, String second) {

    // 正负号判断标志

    boolean flag = false;

    if (first.charAt(0) == '-') {

    flag = !flag;

    first = first.substring(1);

    }

    if (second.charAt(0) == '-') {

    flag = !flag;

    second = second.substring(1);

    }

    // 小数点的位置

    int aPoints = first.length() - first.indexOf('.') - 1;

    int bPoints = second.length() - second.indexOf('.') - 1;

    int pointPos = aPoints + bPoints; // 结果的小数点位置

    // 删除小数点

    StringBuffer aBuffer = new StringBuffer(first.replaceAll("\\.", ""));

    StringBuffer bBuffer = new StringBuffer(second.replaceAll("\\.", ""));

    int[] a = string2IntArray(aBuffer.toString());

    int[] b = string2IntArray(bBuffer.toString());

    int[] result = new int[a.length + b.length - 1]; // 保存结果的数组

    // 计算

    for (int i = 0; i < a.length; i++) {

    for (int j = 0; j < b.length; j++) {

    result[i + j] += a[i] * b[j];

    }

    }

    // result中的某一位大于9的话需要进位

    for (int i = result.length - 1; i >= 0; --i) {

    if (result[i] > 9) {

    result[i - 1] += result[i] / 10;

    result[i] = result[i] % 10;

    }

    }

    StringBuffer buffer = new StringBuffer(); // 将result数组转换为字符串

    for (int i = 0; i < result.length; ++i) {

    // 添加小数点

    if(result.length - i == pointPos) {

    buffer.append(".");

    }

    buffer.append(String.valueOf(result[i]));

    }

    if (buffer.indexOf(".") != -1)

    {

    // 删除最开始的0

    int i = 0;

    while (i < buffer.length()) {

    if (buffer.length() > 2 && buffer.charAt(i+1) == '.') { // 小数点前只有一个数 0.

    break;

    } else if (buffer.charAt(i) == '0') { // 删除最前边的0

    buffer.deleteCharAt(i);

    i = 0;

    continue;

    } else { // 当第一位不是0的时候

    break;

    }

    }

    // 删除末尾的0

    i = buffer.length() - 1;

    while (i >= 0) {

    if (buffer.length() > 2 && buffer.charAt(i-1) == '.') { // 小数点后直接是数字

    break;

    } else if (buffer.charAt(i) == '0') { // 删除末尾的0

    buffer.deleteCharAt(i);

    i = buffer.length() - 1;

    continue;

    } else { // 当最后一位不是0的时候

    break;

    }

    }

    }

    // 根据符号位, 返回值的正负标志

    if (flag) {

    return "-" + buffer.toString();

    } else {

    return buffer.toString();

    }

    }

    /**

    * 将字符串装换为数组

    * @param number

    * @return

    */

    private static int[] string2IntArray(String number) {

    // 判断输入是否符合浮点数的要求

    Pattern pattern = Pattern.compile("^(-?\\d+|\\d*)\\.?\\d*$");

    Matcher matcher = pattern.matcher(number);

    if (!matcher.find()) {

    throw new IllegalArgumentException("输入的数不正确!");

    }

    int[] result = new int[number.length()];

    for (int i = 0; i < number.length(); i++) {

    result[i] = (int) (number.charAt(i) - '0');

    }

    return result;

    }

    }

    运行结果如下:

    1. 错误输入的判断

    Input two large integers:

    1a*a22

    Exception in thread "main" java.lang.IllegalArgumentException: 输入的数不正确!

    at BigNumber.string2IntArray(BigNumber.java:132)

    at BigNumber.bigNumberMultiply(BigNumber.java:54)

    at BigNumber.main(BigNumber.java:22)

    2. 带负数的运算, 前后带有0的情况

    Input two large integers:

    -23424.2300*02345.23400000

    -54935300.61982

    python中计算的结果如下

    Python 2.6.5

    >>> -23424.2300*02345.23400000

    -54935300.619819999

    可以看出python的结果是有失真的

    展开全文
  • double result = 1.0 - 0.9;System.out.println(result);//0.09999999999999998出现这种结果的原因:float和double类型尤其不适合用于货币运算,因为要让一个float或double精确的表示0.1或者任何...1.十进制整数转...

    double result = 1.0 - 0.9;

    System.out.println(result);//0.09999999999999998

    出现这种结果的原因:float和double类型尤其不适合用于货币运算,因为要让一个float或double精确的表示0.1或者任何其他负数次方值是不可能的(十进制系统中不能准确的表示出1/3,同样二进制系统也不能准确的表示1/10)。

    1.十进制整数转为二进制数:

    例子:11表示成二进制数:

    11/2 =5 余1

    5/2 = 2 余1

    2/2 = 1 余0

    1/2 = 0 余1

    0结束,11二进制表示为(从下往上):1011

    注意:只要遇到除以后的结果为0就结束了。所有的整数除以2一定能够最终得到0,但是小数就不能,小数转变为二进制的算法就有可能会无限循环下去。

    2.十进制小数转为二进制数

    算法是乘以2知道没有了小数为止,例子:

    0.9表示成二进制数:

    0.9*2 = 1.8 取整数部分:1

    0.8*2 = 1.6 取整数部分:1

    0.6*2 = 1.2 取整数:1

    0.2*2 = 0.4 取整数:0

    0.4*2 = 0.8 取整数:0

    0.8*2 = 1.6 取整数:1

    。。。。

    0.9二进制表示为(从上往下):1100100100100.......

    注意:上面的计算过程循环了,也就是说乘以2永远不能消灭小数部分,这样算法将无限下去。显然,小数的二进制表示有时是不能精确的。道理很简单,十进制系统中不能准确的表示出1/3,同样二进制也无法准确的表示1/10。这也是浮点型出现精度丢失问题的主要原因。

    解决方案一:

    如果不介意记录十进制的小数点,而且数值不大,那么可以使用long,int等基本类型,

    int resultInt = 10 -9;

    double result  = (double)resultInt / 100;//自己控制小数点

    解决方案二:

    使用BigDecimal,而且需要在构造参数使用String类型.

    float和double只能用来做科学计算或者工程计算,在商业计算等精确计算中,要用java.math.BigDecimal。

    在《EffectiveJava》这本书中就给出了一个解决方法。该书中也指出,float和double只能用来做科学计算或者是工程计算,在商业计算等精确计算中,我们要用java.math.BigDecimal。

    BigDecimal类一个有4个方法,我们只关心对我们解决浮点型数据进行精确计算有用的方法,即

    BigDecimal(double value) // 将double型数据转换成BigDecimal型数据

    思路很简单,我们先通过BigDecimal(double

    value)方法,将double型数据转换成BigDecimal数据,然后就可以正常进行精确计算了。等计算完毕后,我们可以对结果做一些处理,比如

    对除不尽的结果可以进行四舍五入。最后,再把结果由BigDecimal型数据转换回double型数据。

    这个思路很正确,但是如果你仔细看看API里关于BigDecimal的详细说明,你就会知道,如果需要精确计算,我们不能直接用double,而非要用

    String来构造BigDecimal不可!所以,我们又开始关心BigDecimal类的另一个方法,即能够帮助我们正确完成精确计算的

    BigDecimal(String value)方法。

    // BigDecimal(String value)能够将String型数据转换成BigDecimal型数据

    那么问题来了,想像一下吧,如果我们要做一个浮点型数据的加法运算,需要先将两个浮点数转为String型数据,然后用

    BigDecimal(String

    value)构造成BigDecimal,之后要在其中一个上调用add方法,传入另一个作为参数,然后把运算的结果(BigDecimal)再转换为浮

    点数。如果每次做浮点型数据的计算都要如此,你能够忍受这么烦琐的过程吗?至少我不能。所以最好的办法,就是写一个类,在类中完成这些繁琐的转换过程。这

    样,在我们需要进行浮点型数据计算的时候,只要调用这个类就可以了。网上已经有高手为我们提供了一个工具类Arith来完成这些转换操作。它提供以下静态

    方法,可以完成浮点型数据的加减乘除运算和对其结果进行四舍五入的操作:

    public static double add(double v1,double v2)

    public static double sub(double v1,double v2)

    public static double mul(double v1,double v2)

    public static double div(double v1,double v2)

    public static double div(double v1,double v2,int scale)

    public static double round(double v,int scale)

    下面会附上Arith的源代码,大家只要把它编译保存好,要进行浮点数计算的时候,在你的源程序中导入Arith类就可以使用以上静态方法来进行浮点数的精确计算了。

    importjava.math.BigDecimal;

    /**

    * 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精

    * 确的浮点数运算,包括加减乘除和四舍五入。

    */

    publicclassArith{

    //默认除法运算精度

    privatestaticfinalintDEF_DIV_SCALE =10;

    //这个类不能实例化

    privateArith(){

    }

    /**

    * 提供精确的加法运算。

    * @param v1 被加数

    * @param v2 加数

    * @return 两个参数的和

    */

    publicstaticdoubleadd(doublev1,doublev2){

    BigDecimal b1 =newBigDecimal(Double.toString(v1));

    BigDecimal b2 =newBigDecimal(Double.toString(v2));

    returnb1.add(b2).doubleValue();

    }

    /**

    * 提供精确的减法运算。

    * @param v1 被减数

    * @param v2 减数

    * @return 两个参数的差

    */

    publicstaticdoublesub(doublev1,doublev2){

    BigDecimal b1 =newBigDecimal(Double.toString(v1));

    BigDecimal b2 =newBigDecimal(Double.toString(v2));

    returnb1.subtract(b2).doubleValue();

    }

    /**

    * 提供精确的乘法运算。

    * @param v1 被乘数

    * @param v2 乘数

    * @return 两个参数的积

    */

    publicstaticdoublemul(doublev1,doublev2){

    BigDecimal b1 =newBigDecimal(Double.toString(v1));

    BigDecimal b2 =newBigDecimal(Double.toString(v2));

    returnb1.multiply(b2).doubleValue();

    }

    /**

    * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到

    * 小数点以后10位,以后的数字四舍五入。

    * @param v1 被除数

    * @param v2 除数

    * @return 两个参数的商

    */

    publicstaticdoublediv(doublev1,doublev2){

    returndiv(v1,v2,DEF_DIV_SCALE);

    }

    /**

    * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指

    * 定精度,以后的数字四舍五入。

    * @param v1 被除数

    * @param v2 除数

    * @param scale 表示表示需要精确到小数点以后几位。

    * @return 两个参数的商

    */

    publicstaticdoublediv(doublev1,doublev2,intscale){

    if(scale<0){

    thrownewIllegalArgumentException(

    "The scale must be a positive integer or zero");

    }

    BigDecimal b1 =newBigDecimal(Double.toString(v1));

    BigDecimal b2 =newBigDecimal(Double.toString(v2));

    returnb1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();

    }

    /**

    * 提供精确的小数位四舍五入处理。

    * @param v 需要四舍五入的数字

    * @param scale 小数点后保留几位

    * @return 四舍五入后的结果

    */

    publicstaticdoubleround(doublev,intscale){

    if(scale<0){

    thrownewIllegalArgumentException(

    "The scale must be a positive integer or zero");

    }

    BigDecimal b =newBigDecimal(Double.toString(v));

    BigDecimal one =newBigDecimal("1");

    returnb.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();

    }

    };

    转自;http://blog.csdn.net/wanted_tao/article/details/52880737

    展开全文
  • javascript的小数点乘法除法实例导语:想要学好Java语言,必不可少的就是它的四则运算,特别是除法。下面的是百分网小编为大家...js在处理小数除法的时候有一个bug,解决的方法可以是:将小数变为整数来处理。...

    javascript的小数点乘法除法实例

    导语:想要学好Java语言,必不可少的就是它的四则运算,特别是乘除法。下面的是百分网小编为大家搜集的javascript的小数点乘法除法实例,希望可以帮到你。

    一、用js计算

    12.32 * 7  结果是多少?答案:86.24000000000001

    为什么会出现这种问题?怎么解决?

    js在处理小数的乘除法的时候有一个bug,解决的方法可以是:将小数变为整数来处理。

    以上的计算可以改为:

    12.32 * 100 * 7 /100

    得出的结果是:86.24,正确。

    另外再计算一下:

    8.80 * 100 * 12 / 100

    结果:105.60000000000002

    38.80也会出现类似的问题。

    精确度增加10倍:

    8.80 * 1000 * 12 / 1000

    结果:105.6

    正常了。

    16.40 * 1000000 * 6 / 1000000

    结果也有问题

    为了让js执行的更准确,在以后的js小数计算中直接将值扩大10000倍,再除以10000,就可以解决问题。

    var num = 38.80;

    var num2 = 13;

    alert(num * 10000 * 12 / 10000);

    被乘和除的这个数经过测试10000最合适,小了有些数字出问题,大了(1000000)有些数字也出问题。

    二、

    Number.prototype.rate=function(){

    varoStr=this.toString();

    if(oStr.indexOf(".")==-1)

    return1;

    else

    returnMath.pow(10,parseInt(oStr.length-oStr.indexOf(".")-1));

    }

    functiontran(){

    args=tran.arguments;

    vartemp=1;

    for(i=0;i

    temp*=args[i]*args[i].rate();

    for(i=0;i

    temp/=args[i].rate();

    returntemp

    }

    alert(tran(11,22.9));

    该解决 办法是比较麻烦的办法,但是却能让你大概了解解决这个问题的实际过程。

    //除法函数,用来得到精确的除法结果

    //说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。

    //调用:accp(arg1,arg2)

    //返回值:arg1除以arg2的精确结果

    function accp(arg1,arg2){

    var t1=0,t2=0,r1,r2;

    try{t1=arg1.toString().split(".")[1].length}catch(e){}

    try{t2=arg2.toString().split(".")[1].length}catch(e){}

    with(Math){

    r1=Number(arg1.toString().replace(".",""))

    r2=Number(arg2.toString().replace(".",""))

    return (r1/r2)*pow(10,t2-t1);

    }

    }

    //给Number类型增加一个p方法,调用起来更加 方便。

    Number.prototype.p = function (arg){

    return accp(this, arg);

    }

    //乘法函数,用来得到精确的'乘法结果

    //说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。

    //调用:accMul(arg1,arg2)

    //返回值:arg1乘以 arg2的精确结果

    function accMul(arg1,arg2)

    {

    var m=0,s1=arg1.toString(),s2=arg2.toString();

    try{m+=s1.split(".")[1].length}catch(e){}

    try{m+=s2.split(".")[1].length}catch(e){}

    return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m)

    }

    // 给Number类型增加一个mul方法,调用起来更加方便。

    Number.prototype.mul = function (arg){

    return accMul(arg, this);

    }

    //加法函数,用来得到精确的加法结果

    //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。

    //调用:accAdd(arg1,arg2)

    // 返回值:arg1加上arg2的精确结果

    function accAdd(arg1,arg2){

    var r1,r2,m;

    try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}

    try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}

    m=Math.pow(10,Math.max(r1,r2))

    return (arg1*m+arg2*m)/m

    }

    //给Number类型增加一个add方法,调用起来更加方便。

    Number.prototype.add = function (arg){

    return accAdd(arg,this);

    }

    【javascript的小数点乘法除法实例】相关文章:

    展开全文
  • /*** js小数乘法*@parameter arg1:被乘数(接受小数和整数)*@parameter arg2:乘数(接受小数和整数)*@parameter fix: 乘积保留几位(接受正负整数以及0)*/function accMul(arg1,arg2,fix) {if(!parseInt(fix...
  • Java小数取余问题求助

    2021-02-27 16:35:57
    2016-09-01 01:19最佳答案楼上的全不明白楼主的意思,楼主要的...严重BS楼上的,尤其是说java语言的那位。我来告诉你这个问题用递推解决首先要你承认一个公式,我是习惯pascal语言的,c++怕写错,反正只是算法,你忍...
  • Java中的小数运算与精度丢掉float、double类型的问题咱们都知道,核算机是运用二进制存储数据的。而往常日子中,大多数情况下咱们都是运用的十进制,因而核算机显示给咱们看的内容大多数也是十进制的,这就使得许多...
  • 项目中有一个小需求,两个整数相除,结果需要保留两位小数,即1.00、0.50这种数据格式。以下做法不行,因为两整数相除,小数点以后的数字会被截断,让运算结果为整数类型,int x = 10;int y = 20;int a = x/y;System...
  • float、double类型的问题我们都知道,计算机是使用二进制存储数据的。而平常生活中,大多数情况下我们...我们先来看看十进制小数转二进制小数的方法对小数点以后的数乘以2,会得到一个结果,取结果的整数部分(不是1...
  • Java的基本数据类型

    千次阅读 2021-03-11 12:10:33
    一、基本数据类型Java有八大基本数据类型分别是:表示整数的类型,表示小数的类型,表示字符的类型(不是字符串类型,要区分来),表示布尔类型的类型。以上是Java的八种基本数据类型,其中要注意的String(字符串)在...
  • Java中的小数使用double和float表示,小数属于浮点型(默认为double)。对于float型的值,则要在数字后加f或F,如12.3F,它在机器中占32位,4个字节来存储,表示精度较低。double是64位。那么一个小数Java中是如何...
  • 为了达到这样的展示效果,本文列举了几个方法:使用java.math.BigDecimal使用java.text.DecimalFormat使用java.text.NumberFormat使用java.util.Formatter使用String.format当然,我们可以借助封装好的类库或者相应...
  • java保留两位小数问题:方式一(四舍五入形式保留两位小数,注意模式ROUND_HALF_UP):四舍五入double f = 111231.5585;BigDecimal b = new BigDecimal(f);double f1 = b.setScale(2, BigDecimal.ROUND_HALF_UP)....
  • java 中提供BigDecimal对小数的精确处理a) 通常用到下面的方法: 保留两位小数, 四舍五入setScale(int newScale, int roundingMode)- newScale:保留的小数位数- roundingMode:精度取值方式roundingMode的取值有...
  • 1. 十进制整数思路: 整数除以2,每次将余数保存起来,商循环除以2,直到商为0为止,然后将所有余数逆序打印出来。例子:23/2 商: 11 余数: 111/2 商: 5 余数: 15/2 商: 2 余数: 12/2 商: 1 余数: 01/2 商: 0 余数: ...
  • java基础之小数计算

    2021-03-06 04:33:22
    项目中会经常用到小数位的计算。很多人第一感觉会想尝试使用float或者double,然而在精准计算,例如金钱计算中,使用float或者double来计算会出现意想不到后果...先用整数加减乘除,再除以小数位。2.使用BigDecimal...
  • java保留两位小数

    2021-03-14 10:17:55
    java保留两位小数问题:方式一:四舍五入double f = 111231.5585;BigDecimal b = new BigDecimal(f);double f1 = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();保留两位小数----------------------------...
  • 该楼层疑似违规已被系统折叠隐藏此楼查看此... import java.text.DecimalFormat; public class Jisuan { private static int CHENG_INDEX; //* 下标private static int CHU_INDEX; // /下标private static int JIA_...
  • 但实际上,即使在一些非常基本的小数运算中,计算的结果也是不精确的。 比如: float f = 0.1f*0.1f; System.out.println(f); 这个结果看上去,不言而喻,应该是0.01,但实际上,屏幕输出却是0.010000001,后面多了...
  • 高精度乘法是大数乘以一个int型的小数,和前面模拟不同,这里不是一位一位的,而是a一位乘以整个数b,当a到最高位且没有进位就结束了。 2.代码模板 方法一: //a为大数,倒序存储,b为int型,返回a*b的结果 ...
  • 1.代码:import java.math.BigDecimal;import java.text.DecimalFormat;import java.text.NumberFormat;public class format {double f = 111231.5585;public void m1() {BigDecimal bg = new BigDecimal(f);double ...
  • 小数固定保留两位小数兼容负数数字检测适配金融大数额核心类public class BigDecimalStringUtil {/*** 数字字符串,转成BigDecima格式,兼容大数字* 并且保留两位小数* @return*/public static String str2...
  • 目录1. 提供精确的加法运算2. 提供精确的减法运算2.1 参数为double类型2.2 参数为字符串类型2.3 减法运算精确小数点位数3. 提供精确的乘法运算4. 提供指定小数点位数的除法运算4.1 除不尽四舍五入4.2 除不尽指定精度...
  • java小数的加减乘除

    千次阅读 2015-12-04 10:27:17
    昨天修改一个项目的时候,突然...单价*数量*折扣=应收金额 或者正常的加减,会突然出现很多个小数, public static void main(String[] args) { double kk = 3.14; kk += 0.37; float ff = 3.14f; ff += 0.37
  • 1,采用大数算法; 2,默认为double直接new float转换,或者是在每个数字上加上f即可; 参考地址: http://zhidao.baidu.com/question/347182188.html 转载于:...
  • How do you multiply a BigDecimal by an integer in Java? I tried this but its not correct.import java.math.BigDecimal;import java.math.MathContext;public class Payment {int itemCost;int totalCost = 0;p...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 19,322
精华内容 7,728
关键字:

java小数乘法

java 订阅