【问题标题】:Is it possible to get floating point error in this case?在这种情况下是否可能出现浮点错误?
【发布时间】:2015-02-25 03:14:30
【问题描述】:

我知道浮点算术很棘手,但我不确定如果在除法之后再进行逆乘,是否会出错。写在代码里,有没有可能,这个方法会返回false

public boolean calculate(float a, float b) {
        float c = a / b;
        return (a == (c * b));
}

【问题讨论】:

    标签: java floating-accuracy floating-point-precision


    【解决方案1】:

    简单的答案是 - 是的。这个例子肯定返回 false:

    public boolean alwaysFalse(){
            float a=Float.MIN_VALUE;
            float b=Float.MAX_VALUE;
            float c = a / b;
            return a == c * b;
    }
    

    更新
    更一般的答案是,false 发生在您的方法中有两种情况:
    1) 当有效位溢出时(即除法计算的位数超过有效位可以容纳的位数)
    2)在指数达到最小值后,如果不丢失有效位的最低有效位,您就不能进一步除法

    您可以为 'a' 构造示例以保证错误 - 例如有效位的最高和最低有效位为 1(二进制):10000...000001e10 等

    【讨论】:

    • 感谢您的回答。是否有任何示例的值不是极端的(无穷大、最小值/最大值、NaN 或零),只是简单的数字?
    • @IvayloToskov 只是数字,就好像你担心 1/3 例如,c 不准确,但如果你将它乘以 3,它会再次四舍五入为 1 .
    【解决方案2】:

    您可以自行检查此类情况。例如这段代码:

    public class Main {
    
    
        public static void main(String[] args) {
            for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
                for (int j = Integer.MIN_VALUE; j < Integer.MAX_VALUE; j++) {
                    if (!calculate(i, j))
                        System.out.println(i + " " + j);
                }
            }
    
        }
    
        public static boolean calculate(float a, float b) {
            float c = a / b;
    
            return (a == (c * b));
        }
    }
    

    这会返回许多情况,例如:

    1 - 6957633
    1 - 6957635
    1 - 6957644

    【讨论】:

    • 在循环中包含 0 以获得更多边缘情况;别担心,这是允许的。
    • 你是对的,我更新了它来做一个完整的暴力搜索。
    • 感谢您的回答!解释将受到高度重视,因为我无法真正理解为什么这些值会导致这种行为。
    【解决方案3】:

    是的。

    calculate(0,0)
    

    返回false,因为c的值是NaN,所以c * b也会是NaN,但是a是0,不等于NaN

    【讨论】:

    • 我忽略了这种情况,你是完全正确的,但我对浮点精度缺陷被利用的情况感兴趣。
    • @IvayloToskov 在这种情况下你是安全的,它永远是true
    • 是否可以使用 0 以外的值?
    • @Evorlor 任意 (X, 0) 对。
    猜你喜欢
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 2015-08-10
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    相关资源
    最近更新 更多