El backend de Java implementa el cálculo de sumas, restas, multiplicaciones, divisiones y proporciones

El backend de Java implementa el cálculo de sumas, restas, multiplicaciones, divisiones y proporciones

La clase API BigDecimal se proporciona en el paquete java.math para realizar operaciones precisas en números con más de 16 dígitos significativos.
Lo que crea BigDecimal es un objeto, por lo que los operadores aritméticos como +, -, *, /, etc. no se pueden usar para realizar operaciones matemáticas directamente en su objeto.

En primer lugar, debe comprender que BigDecimal tiene 4 métodos de construcción:

	//创建一个具有参数所指定整数值的对象
	BigDecimal(int)
	//创建一个具有参数所指定双精度值的对象
	BigDecimal(double)
	//创建一个具有参数所指定整数值的对象
	BigDecimal(long)
	//创建一个具有参数所指定以字符串表示的数值的对象
	BigDecimal(String)

	//这里对比了两种形式,第一种直接value写数字的值,第二种用string来表示
	BigDecimal num1 = new BigDecimal(0.005);
    BigDecimal num2 = new BigDecimal(1000000);
    BigDecimal num3 = new BigDecimal(-1000000);    
    //尽量用字符串的形式初始化
    BigDecimal num12 = new BigDecimal("0.005");
    BigDecimal num22 = new BigDecimal("1000000");
    BigDecimal num32 = new BigDecimal("-1000000");

1. Sumas, restas, multiplicaciones y divisiones

	//加法 add()
    BigDecimal result1 = num1.add(num2);
    BigDecimal result12 = num12.add(num22);
 
    //减法 subtract()
    BigDecimal result2 = num1.subtract(num2);
    BigDecimal result22 = num12.subtract(num22);
 
    //乘法 multiply()
    BigDecimal result3 = num1.multiply(num2);
    BigDecimal result32 = num12.multiply(num22);
 
    //绝对值 abs()
    BigDecimal result4 = num3.abs();
    BigDecimal result42 = num32.abs();
 
    //除法 divide()
    //num1、num12 除数, 20 精确小数位,  BigDecimal.ROUND_HALF_UP 舍入模式
    BigDecimal result5 = num2.divide(num1,20,BigDecimal.ROUND_HALF_UP);
    BigDecimal result52 = num22.divide(num12,20,BigDecimal.ROUND_HALF_UP);

	//去除末尾多余的0:
	new BigDecimal("100.000").stripTrailingZeros().toPlainString();

Envíe todos los resultados aquí para ver los resultados
Hay una diferencia aquí, por lo que se recomienda usar una cadena para la inicialización
inserte la descripción de la imagen aquí
※ Nota:

1) El número en System.out.println() es de tipo doble por defecto, y el cálculo decimal de tipo doble es inexacto.

2) Cuando se usa el método de construcción de la clase BigDecimal para pasar el tipo doble, ¡el resultado del cálculo también es inexacto!

Debido a que no todos los números de punto flotante se pueden representar con precisión como un valor de tipo doble, algunos valores de punto flotante no se pueden representar con precisión como un valor de tipo doble, por lo que se representará como su valor de tipo doble más cercano. Debe usar el constructor que pasa en String en su lugar. Este punto se explica en la anotación del constructor de la clase BigDecimal.

El parámetro division divide() usa

Al usar la función de división para dividir, debe establecer varios parámetros, lugares decimales precisos y modo de redondeo, de lo contrario, se producirá un error.
Podemos ver que los parámetros de la configuración de la función de división son los siguientes

	//即为(BigDecimal divisor 除数, int scale 精确小数位,  int roundingMode 舍入模式)
	Public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)

Pero hay muchos tipos de modos de redondeo BigDecimal.ROUND_XXXX_XXX, ¿qué significan específicamente?

Los ocho modos de redondeo se explican a continuación.

1)ROUND_UP

El modo de redondeo para redondear desde cero.

Incremente siempre el número antes de descartar la parte distinta de cero (siempre agregue 1 al número que precede a la parte descartada distinta de cero).

Tenga en cuenta que este modo de redondeo nunca reduce el tamaño del valor calculado.

2)REDONDO_ABAJO

Modo de redondeo cercano a cero.

Nunca incremente un número hasta que se descarte una parte (nunca sume 1 al número que precede a la parte descartada, es decir, trunque).

Tenga en cuenta que este modo de redondeo nunca aumenta el tamaño del valor calculado.

3)TECHO_REDONDO

Modo de redondeo hacia el infinito positivo.

Si BigDecimal es positivo, el comportamiento de redondeo es el mismo que ROUND_UP;

Si es negativo, el comportamiento de redondeo es el mismo que ROUND_DOWN.

Tenga en cuenta que este modo de redondeo nunca reduce el valor calculado.

4)PISO_REDONDO

Modo de redondeo cerca del infinito negativo.

Si BigDecimal es positivo, el comportamiento de redondeo es el mismo que ROUND_DOWN;

Estilo negrita Si es negativo, el comportamiento de redondeo es el mismo que ROUND_UP.

Tenga en cuenta que este modo de redondeo nunca aumenta el valor calculado.

5)ROUND_HALF_UP

Redondea hacia el número "más cercano" o hacia arriba si dos números adyacentes son equidistantes entre sí.

Si la fracción descartada es >= 0,5, el comportamiento de redondeo es el mismo que ROUND_UP; de lo contrario, el comportamiento de redondeo es el mismo que ROUND_DOWN.

Tenga en cuenta que este es el modo de redondeo que la mayoría de nosotros aprendimos en la escuela primaria (redondeo a la mitad).

6)ROUND_HALF_DOWN

Un modo de redondeo que redondea hacia el número "más cercano" o redondea hacia arriba si dos números adyacentes son equidistantes entre sí.

Si la fracción descartada es > 0,5, el comportamiento de redondeo es el mismo que ROUND_UP; de lo contrario, el comportamiento de redondeo es el mismo que ROUND_DOWN (redondeo hacia arriba).

7)ROUND_HALF_EVEN

Redondea hacia el número "más cercano" o hacia el número par adyacente si la distancia a dos números adyacentes es igual.

Si el número a la izquierda de la parte descartada es impar, el comportamiento de redondeo es el mismo que ROUND_HALF_UP;

Si es par, el comportamiento de redondeo es el mismo que ROUND_HALF_DOWN.

Tenga en cuenta que este modo de redondeo minimiza los errores de acumulación al repetir una serie de cálculos.

Este modo de redondeo también se conoce como "Redondeo bancario" y se usa principalmente en los Estados Unidos. Redondeando hacia arriba, cinco puntos en dos casos.

Si el dígito anterior es un número impar, ingréselo, de lo contrario, deséchelo.

El siguiente ejemplo conserva 1 lugar decimal, por lo que el resultado de este método de redondeo.

1,15>1,2 1,25>1,2

8)ROUND_UNNECESSARY

Afirma que la operación solicitada tiene un resultado exacto, por lo que no se requiere redondeo.

Se lanza una ArithmeticException si se especifica este modo de redondeo para una operación que obtiene un resultado exacto.

Por ejemplo: Calcular el resultado de 1÷3 (el último ROUND_UNNECESSARY reportará un error si el resultado es un decimal infinito)
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

2. Compara el tamaño


	//前提为a、b均不能为null
	BigDecimal a = new BigDecimal("xx");
    BigDecimal b = new BigDecimal("xx");
	
	if(a.compareTo(b) == -1){
    
    
	    System.out.println("a小于b");
	}
	 
	if(a.compareTo(b) == 0){
    
    
	    System.out.println("a等于b");
	}
	 
	if(a.compareTo(b) == 1){
    
    
	    System.out.println("a大于b");
	}
	 
	if(a.compareTo(b) > -1){
    
    
	    System.out.println("a大于等于b");
	}
	 
	if(a.compareTo(b) < 1){
    
    
	    System.out.println("a小于等于b");
	}

3. Resumen de BigDecimal

Use BigDecimal cuando se requiera un cálculo decimal preciso. El rendimiento de BigDecimal es peor que el de double y float, especialmente cuando se trata de operaciones grandes y complejas. Por lo tanto, no es necesario usar BigDecimal para cálculos generales de precisión. Intente usar constructores cuyo tipo de parámetro sea String.

BigDecimal es inmutable y se generará un nuevo objeto cada vez que se realicen las cuatro operaciones aritméticas, así que recuerde guardar el valor después de la operación al realizar sumas, restas, multiplicaciones y divisiones.

Recomendación de herramienta

package com.vivo.ars.util;
import java.math.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;
    }
}

La ley de las cosas buenas: Todo será una buena cosa al final, si no es una buena cosa, significa que aún no es el final.

Supongo que te gusta

Origin blog.csdn.net/Cike___/article/details/123049211
Recomendado
Clasificación