【问题标题】:Java: understanding double (and normalization)Java:理解双重(和规范化)
【发布时间】:2014-02-18 16:40:17
【问题描述】:

我正在尝试学习一些关于机器人技术和 Java 的知识。在我的尝试中,我编写了一个函数,它(应该)采用一个名为 q(0.2,0.2,0.2,0.2,0.2) 的统一数组,与另一个数组世界相比,根据 Z 值将该数组中的每个值乘以 0.6 或 0.2 (0,1,1,0,0) 表示与数组世界比较值 Z 的命中或未命中,最后返回一个新的统一数组。

所以: 1.) 循环 (0,1,1,0,0) 2.) 如果 i!=Z 比 i*0.2,如果 i=Z 比 i*0.6 3.) 将 q 中的所有新值加到一个称为 normalize 的双精度数中 4.) 对q中的每个值进行归一化(值/归一化)

下面是函数:

    public static final double pHit = 0.6;
    public static final double pMiss = 0.2;
    public static int[] world = {0,1,1,0,0};
    public static List<Double> q = new ArrayList<Double>();

    public static List<Double> sense(int Z){
        double normalize = 0;
        for(int i=0;i < q.size();i++){
            if(Z == world[i]){
                q.set(i, (q.get(i) * pHit));
            }
            else{
                q.set(i, (q.get(i) * pMiss));
            }
        }
        //Normalize
        for(int i=0;i < q.size();i++){
            normalize += q.get(i);
        }
        for(int i=0;i<q.size();i++){
            q.set(i, q.get(i)/normalize);
        }
        return q;   
    }

如果我将 world 设置为 (0,1,0,0,0) 并将 Z 设置为 1,我会得到以下结果: 0.14285714285714288 0.4285714285714285 0.14285714285714288 0.14285714285714288 0.14285714285714288

这很好地归一化(总和 = 1)。

但是,如果我将 world 设置为 (0,1,1,0,0) 并将 Z 设置为 1,我会得到一个奇怪的结果: 0.1111111111111111 0.3333333333333332 0.3333333333333332 0.1111111111111111 0.1111111111111111

这“标准化”为 0.9999999999999998 ?

非常感谢您的任何意见!

【问题讨论】:

    标签: java double normalization


    【解决方案1】:

    双数并不是实数线的完美表示。它们只有大约 16 位的精度。在连续的计算中,可能会产生错误,有时甚至是灾难性的。在你的情况下,这还没有发生,所以要高兴。

    0.1 的值就是一个很好的例子。在 IEEE 浮点中,它只有一个近似表示。作为二进制分数,它是 0.0[0011],其中方括号中的部分永远重复。这就是为什么浮点数(包括双精度数)可能不是表示价格的最佳选择。

    我强烈建议阅读这篇经典摘要:

    http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

    【讨论】:

    • 不幸的是,我一遍又一遍地使用这个函数,所以它就像你写的那样发生了:一个灾难性的错误! :) 那么,如果我理解正确,我会坚持使用 BigDecimal,这会大大减慢我的计算速度吗?任何人都知道python在这种情况下使用什么?我在 python 中看到了我的代码示例,但是根本没有说明他们甚至使用了什么样的变量......
    • 您真的需要比双精度更精确的结果吗? BigDecimal 有同样的问题。三分之一无法在其中准确表示。
    • @user2826751 浮点表示永远不会是完美的。为什么归一化 0.0000000000000001 的错误是一个问题?
    • NB Python 在其默认输出模式下不会像 Java 那样打印 16 位小数,因此它会四舍五入到 1.0 或类似值。它在内部处理相同的错误。
    【解决方案2】:

    浮点数在计算机上并不能精确表示。因此,在将浮点值相乘时,您会从精确值中得到非常小的分数。

    请参阅this answer,因为它更深入地了解浮动表示并引用此Floating-Point Arithmetic 文章。

    【讨论】:

      【解决方案3】:

      欢迎来到浮点数的世界! 我没有尝试详细了解您的代码,但结果 0.99999999999999998 是完全正常的。我建议您阅读一些关于floating point numbers 及其精度的内容。

      【讨论】:

        猜你喜欢
        • 2013-05-10
        • 2016-08-11
        • 1970-01-01
        • 2014-07-06
        • 1970-01-01
        • 1970-01-01
        • 2021-06-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多