Java(建议)——将 double 实现为两个整数?

Java (suggestion) - implement double as two integers?

提问人:milkamar 提问时间:9/29/2022 最后编辑:Mushroomatormilkamar 更新时间:9/29/2022 访问量:112

问:

在 java 中,double 需要 64 位,但存储(或计算)数字时会非常精确。 例如,以下代码:

 double a = 10.125d;
 double b = 7.065d;
 System.out.println(a-b);

打印出来而不是 .3.05999999999999963.06

那么,问题来了——利用这 64 位来存储两个 32 位整数(第一个表示整个部分,第二个表示小数部分)怎么样? 那么计算会很精确,对吧?

具有未处理的十进制传输的朴素伪代码实现:

primitive double {
    int wholePart;
    int decimalPart;
    
    public double + (double other) {
        return double (this.wholePart + other.wholePart, this.decimalPart + other.decimalPart);
    }
    
    //other methods in the same fashion
    
    public String toString() {
        return wholePart + "." + decimalPart;
    }
}

Java 是否有理由不精确地存储 double 并且不使用上述实现?

Java 浮点 精度

评论

0赞 Gatusko 9/29/2022
Java 不会不精确地存储该值。检查这个问题并理解它。stackoverflow.com/questions/21895756/......
2赞 Mihe 9/29/2022
你不精确地称之为浮点数,由广泛使用的 IEEE 754 标准化(包括 CPU)。它们的存储方式允许非常小和非常大的数字,以及正和负无穷大和“不是数字”。因为它们是二进制的,所以你不能精确地表示某些十进制值,但这只是你从十进制系统中知道的:你不能用十进制数表示三分之一,因为你需要无限数量的小数。
3赞 Eric Postpischil 9/29/2022
没有固定大小的编码可以存储所有实数。不是浮点,不是定点,不是整数,不是整数+分数,什么都没有。您唯一能做的就是使用适合您的应用程序的格式。十进制格式,无论是您建议的还是另一种,都可能适合匹配人类的计算和期望,因为它们使用有限的十进制数字进行计算。但他们在简单的任务上失败了,比如计算一美元卖三件商品的单价(1/3不能用小数表示),或者完全精确地积累复利。

答:

0赞 Mushroomator 9/29/2022 #1

您的解决方案存在一个大问题。 是有符号的,因此它将能够具有没有意义的负小数部分。除此之外,您不能使用解决方案存储相同范围的值,并且会丢失值 和 。查看浮点是如何以二进制形式存储的,例如在这个 SO 问题中,以了解为什么会这样,或者阅读 IEEE 754,这是定义浮点数如何以二进制形式存储的标准。intDouble.NEGATIVE_INFINITYDouble.NaNDouble.POSITIVE_INFINITY

但是,是的,一般来说,如果您需要精度,最好使用整数算术而不是浮点算术(同样,原因请参阅上面链接的问题)。最简单的方法是选择另一个单位/您需要的最小单位。

例如,假设您要以欧元计算价格。如果您将它们存储为这样,您将面临不准确的风险,这在处理价格时是您真正不希望的。因此,与其存储金额,不如存储多少美分(此处的最小单位)成本,您将消除问题。floats

对于大整数,还有 BigInteger,因此该方法也适用于大或非常小的浮点值。