首页 > 解决方案 > 验证是否创建了大小数而没有任何精度损失

问题描述

我有一个接受 BigDecimal 的方法。我想确保它的十进制值没有精度损失(即)输入到大十进制是完全按原样存储的。我的理解是,当我尝试将无限双精度转换为大十进制时会发生精度损失,因此建议使用双精度的字符串表示来创建大十进制。基本上,我想确定是否使用 BigDecimal(String) 为这种无限双打构造了大十进制。

根据我在通过doc后的理解,在大十进制转换期间导致精度损失的输入双精度值始终具有非常大的幅度,不适合 64 位。示例:0.1。因此,这种大小数的字符串和双精度值表示将不匹配。是否足以说当字符串和双精度值不匹配时发生了精度损失?
例如:
BigDecimal 十进制 = new BigDecimal(0.1);
System.out.println(decimal.toString()) // 打印 0.1000000000000000055511151231257827021181583404541015625
System.out.println(decimal.doubleValue()) // 打印 0.1。
大十进制的字符串和双精度值不同,因此发生精度损失。

标签: doublebigdecimal

解决方案


如果您允许 BigDecimal 是算术的结果,那么这个想法就会失效。

如果您要要求 BigDecimal 是十进制字符串转换的直接、未修改的结果,那么在您的方法中要求 String 参数并将其转换为 BigDecimal 会简单得多。

以下程序是尝试实施和测试您的有效性检查。该变量third是在没有任何双精度的情况下计算的,仅使用十进制字符串和 BigDecimal,但未通过测试。

import java.math.BigDecimal;
import java.math.RoundingMode;

public strictfp class Test {
    public static void main(String[] args) {
        BigDecimal third = BigDecimal.ONE.divide(new BigDecimal("3"), 30, RoundingMode.HALF_EVEN);
        testIt(new BigDecimal("0.1"));
        testIt(new BigDecimal(0.1));
        testIt(third);
    }

    static void testIt(BigDecimal in) {
        System.out.println(in+" "+isValid(in));
    }

    static boolean isValid(BigDecimal in) {
        double d = in.doubleValue();
        String s1 = in.toString();
        String s2 = Double.toString(d);
        return s1.equals(s2);
    }
}

输出:

0.1 true
0.1000000000000000055511151231257827021181583404541015625 false
0.333333333333333333333333333333 false

推荐阅读