Java中求Logn/log2 的精度问题

目录
  • java求Logn/log2精度
    • 例如
    • 程序如下:
  • java 处理高精度计算
    • 使用的BigDecimal类的时候需要注意的地方:

java求Logn/log2精度

经过本人测试,java 中 , 一直到 2的492 次方(这么大的数,平时够用了) ;用 Math.log(n) / Math.log(x) 公式都会产生一个整数

例如

  int x = 2 ;
  double n = Math.pow(2, 234)
  System.out.println(Math.log(n) / Math.log(x));

输出的是 234.0

而到了 2的493次方,结果是493.00000000000006 ; 所以,平时用这个公式来确定n是否是2的整数次幂足够了!

程序如下:

public class Test {
 public static void main(String[] args) {
 // System.out.println(Math.pow(2, 23));
  int x = 2 ;
  double n = Math.pow(2, 493) ;
  System.out.println(Math.log(n) / Math.log(x));
 }
}

java 处理高精度计算

Double.valueOf(String) and Float.valueOf(String)都会丢失精度。

为了解决这个问题,需要用到BigDecimal类。

使用的BigDecimal类的时候需要注意的地方:

1. 在实例化BigDecimal 的时候用 new BigDecimal(String) 代替new BigDecimal(double) ,new BigDecimal(float)在《Effective Java》书中有提到

2. 比较两个数的时候用compareTo 小于返回-1 , 等于返回0 , 大于返回1

import java.math.BigDecimal;
public class ArithmeticUtil {
    /*
     * 小数精确的位数
     */
    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);
    } 

    /**
     * 提供精确的加法运算。 String
     *
     * @param v1
     *            被加数
     * @param v2
     *            加数
     * @return 两个参数的和
     */
    public static String strAdd(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 v
     * @param scale
     * @return
     */
    public static BigDecimal 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);
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP);
    } 

    /**
     * 提供精确的减法运算。String
     *
     * @param v1
     *            被减数
     * @param v2
     *            减数
     * @return 两个参数的差
     */
    public static String strSub(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);
    } 

    /**
     * 提供精确的乘法运算。 保留scale 位小数
     *
     * @param v1
     *            被乘数
     * @param v2
     *            乘数
     * @return 两个参数的积
     */
    public static double mul2(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);
    } 

    /**
     * 提供精确的乘法运算。 保留scale 位小数 String
     *
     * @param v1
     *            被乘数
     * @param v2
     *            乘数
     * @return 两个参数的积
     */
    public static String strMul2(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 BigDecimal div(String v1, String v2) {
        return div(v1, v2, DEF_DIV_SCALE);
    } 

    /**
     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后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 BigDecimal 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(v2);
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP);
    } 

    /**
     * 精确的除法运算。除不尽时,由scale参数指 定精度 四舍五入。string
     *
     * @param v1
     *            被除数
     * @param v2
     *            除数
     * @param scale
     *            表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static String strDiv(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.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
    } 

    /**
     * 精确的除法运算。除不尽时,由scale参数指 定精度 四舍五入。string
     *
     * @param v1
     *            被除数
     * @param v2
     *            除数
     * @param scale
     *            表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static BigDecimal bigDiv(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.divide(b2, scale, BigDecimal.ROUND_HALF_UP);
    }
    /**
     * 取余数  string
     * @param v1
     * @param v2
     * @param scale
     * @return
     */
    public static BigDecimal strRemainder(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);
    }
    /**
     * 取余数  string
     * @param v1
     * @param v2
     * @param scale
     * @return  string
     */
    public static String strRemainder2Str(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();
    } 

    /**
     * 比较大小 如果v1 大于v2 则 返回true 否则false
     * @param v1
     * @param v2
     * @return
     */
    public static boolean strcompareTo(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;
    } 

    /**
     * 比较大小 如果v1 大于等于v2 则 返回true 否则false
     * @param v1
     * @param v2
     * @return
     */
    public static boolean strcompareTo2(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;
    } 

    /**
     * 比较大小 如果v1 等于v2 则 返回true 否则false
     * @param v1
     * @param v2
     * @return
     */
    public static boolean strcompareTo3(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;
    } 

    /**
     * 取余数  BigDecimal
     * @param v1
     * @param v2
     * @param scale
     * @return
     */
    public static BigDecimal bigRemainder(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 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));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    } 

    /**
     * 提供精确的小数位四舍五入处理。string
     *
     * @param v
     *            需要四舍五入的数字
     * @param scale
     *            小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static String strRound(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();
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 详解java中BigDecimal精度问题

    一.背景 在实际开发中,对于 不需要任何准确计算精度的属性可以直接使用float或double,但是如果需要精确计算结果,则必须使用BigDecimal,例如价格.质量. 为什么这么说,主要有两点 1.double计算会有精度丢失问题 2.在除法运算时,BigDecimal提供了丰富的取舍规则.(double虽然可以通过NumberFormat进行四舍五入,但是NumberFormat是线程不安全的) 对于精度问题我们可以看下实际的例子 public static void main(Strin

  • 浅谈Java中的高精度整数和高精度小数

    在实际编码中,会遇到很多高精度的事例,比如,在计算金钱的时候就需要保留高精度小数,这样计算才不会有太大误差: 在下面的代码中,我们验证了,当两个float型的数字相加,得到的结果和我们的预期结果是有误差的,为了减小和防止这种误差的出现,我们需要使用BigInteger类和BigDecimal类来计算. package com.ietree.base.number; import java.math.BigDecimal; import java.math.BigInteger; public c

  • Java中浮点数精度问题的解决方法

    问题描述 在项目中用Java做浮点数计算时,发现对于4.015*100这样的计算,结果不是预料中的401.5,而是401.49999999999994.如此长的位数,对于显示来说很不友好. 问题原因:浮点数表示 查阅相关资料,发现原因是:计算机中的浮点数并不能完全精确表示.例如,对于一个double型的38414.4来说,计算机是这样存储它的: 转成二进制:1001011000001110.0110011001100110011001100110011001100 转成科 学计数法:1.0010

  • java精度计算代码 java指定精确小数位

    本文实例为大家分享了java指定精确小数位的具体代码,供大家参考,具体内容如下 java代码: public class App2 { public static void main(String[] args) { String val = checkNumber("10.1234155", 2, 6).toString(); System.out.println(val); } public static BigDecimal checkNumber(String number,

  • JAVA浮点数计算精度损失底层原理与解决方案

    问题: 对两个double类型的值进行运算,有时会出现结果值异常的问题.比如: System.out.println(19.99+20); System.out.println(1.0-0.66); System.out.println(0.033*100); System.out.println(12.3/100); 输出: 39.989999999999995 0.33999999999999997 3.3000000000000003 0.12300000000000001 Java中的简

  • Java中求Logn/log2 的精度问题

    目录 java求Logn/log2精度 例如 程序如下: java 处理高精度计算 使用的BigDecimal类的时候需要注意的地方: java求Logn/log2精度 经过本人测试,java 中 , 一直到 2的492 次方(这么大的数,平时够用了) :用 Math.log(n) / Math.log(x) 公式都会产生一个整数 例如 int x = 2 ; double n = Math.pow(2, 234) System.out.println(Math.log(n) / Math.lo

  • java中double转化为BigDecimal精度缺失的实例

    java中double转化为BigDecimal精度缺失实例 @SuppressWarnings("static-access") public static void main(String[] args) { System.out.println(3215.10/2); BigDecimal bd = new BigDecimal(3215.10/2); System.out.println(bd); System.out.println(bd.setScale(2, bd.ROU

  • Java中求最大值的4种方法实例代码

    前言 本文主要给大家分享了关于java求最大值的4中方法,文中给出了完整的示例代码,下面话不多少了,来一起看看吧 示例代码: /** *@author Prannt *求最大值(或最小值) *本例以int数据类型为例,可指定其他数据类型 */ //方法一:直接法,求最小值类似 public class Deno05ArrayMax { public static void main(String[] args) { //数据类型可指定 int [] array = {5,15,20,30,100

  • java中求高精度除法,要求保留N位小数

    目录 求高精度除法,要求保留N位小数 题目要求 java 大数处理和高精度小数处理(so easy) 简单的例子: 部分简单代码 求高精度除法,要求保留N位小数 题目要求 高精度除法,要求保留N位小数(四舍五入),并且当整数部分为0时去除0的显示 import java.math.BigDecimal; import java.util.Scanner; public class BD { public static void main(String[] args) { Scanner scan

  • 浅谈Java中hashCode的正确求值方法

    本文研究的主要是Java中hashCode的正确求值方法的相关内容,具体如下. 散列表有一项优化,可以将对象的散列码(hashCode)缓存起来,如果散列码不匹配,就不会检查对象的等同性而直接认为成不同的对象.如果散列码(hashCode)相等,才会检测对象是否相等(equals). 如果对象具有相同的散列码(hashCode),他们会被映射到同一个散列桶中.如果散列表中所有对象的散列码(hashCode)都一样,那么该散列表就会退化为链表(linked list),从而大大降低其查询效率. 一

  • Java中BigDecimal精度和相等比较的坑

    为什么要有BigDecimal ,他是干什么的 float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的.然而,它们没有提供完全精确的结果,所以不应该被用于要求精确结果的场合.但是,商业计算往往要求结果精确,这时候就要使用BigDecimal啦. 什么是BigDecimal BigDecimal 由任意精度的整数非标度值 和32 位的整数标度 (scale) 组成.如果为零或正数,则标度是小数点后的

  • Java中自己如何实现log2(N)

    目录 Java 实现log2(N) 换底公式: 实现为: log以2为底的对数 Java 实现log2(N) 在刷题过程中需要使用到log2(N),但是java中只有log(double),log10(double)等等函数,这时用换底公式就可以自己实现log2(N). 换底公式: 所以:log2N=logeN/loge2,logeN代表以e为底的N的对数,loge2代表以e为底的2的对数. 实现为: public double log2(double N) { return Math.log(

  • Java中BigDecimal除法使用不当导致精度问题

    目录 I. 问题抛出 II. 源码定位 1. 整形传参构造 2. 浮点传参 3. String传参 4. 小结 在使用BigDecimal的除法时,遇到一个鬼畜的问题,本以为的精度计算,结果使用返回0,当然最终发现还是使用姿势不对导致的,因此记录一下,避免后面重蹈覆辙 I. 问题抛出 在使用BigDecimal做高精度的除法时,一不注意遇到了一个小问题,如下 @Test public void testBigDecimal() { BigDecimal origin = new BigDecim

随机推荐