Java:理解双重(和规范化)

时间:2014-01-27 17:36:30

标签: java double normalization

我正在尝试学习机器人技术和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的double中 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

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

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

这“标准化”为0.9999999999999998?

非常感谢任何意见!

3 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分:0)

浮点数未在计算机上准确显示。因此,当将浮动值相乘时,您将从精确值中获得非常小的分数。

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

答案 2 :(得分:0)

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