java - Java HashMap 拷贝构造函数为什么会影响 float 精度?

标签 java floating-point copy-constructor

我有一些代码在 float 映射上计算线性组合,并遇到了使用复制构造函数的有趣副作用。

如果我计算两个 map 中值的线性组合并将其与使用这些 map 的两个副本中的值计算的线性组合进行比较,计算结果实际上略有不同(在10^-7) 结果似乎是浮点精度。

为什么会这样?

下面是一些示例代码:

import java.util.*;

public class WTF {
    public static void main(String[] args) {
        Random rand = new Random();

        for (int c = 0; c < 1000; c++) {
            Map<String, Float> weights = new HashMap<String, Float>();
            Map<String, Float> values = new HashMap<String, Float>();

            for (int j = 0; j < 10; j++) {
                weights.put("sig" + j, Float.valueOf(rand.nextFloat()));
                values.put("sig" + j, Float.valueOf(rand.nextFloat()));
            }

            Map<String, Float> weightsCopy = new HashMap<String, Float>(weights);
            Map<String, Float> valuesCopy = new HashMap<String, Float>(values);

            float score1 = getScore(weights, values);
            float score2 = getScore(weightsCopy, valuesCopy);

            if (score1 != score2) {
                System.out.println(score1-score2);
            }
        }
    }

    public static float getScore(Map<String, Float> weights, Map<String, Float> values) {
        float score = 0.0f;
        for (String name : weights.keySet()) {
            Float weight = weights.get(name);
            Float value = values.get(name);
            score += weight.floatValue() * value.floatValue();
        }
        return score;
    }
}

更新:

同样的问题也适用于 putAll 操作。使用它来“复制”HashMap 会导致相同的浮点精度问题。

最佳答案

map 中的顺序发生变化,导致操作以不同的顺序运行。简单计算的输出变化示例(注意翻转的 d 和 e):

class WTF {
    public static void main(String[] args) {
        final float a = 0.42890447f * 0.37233013f;
        final float b = 0.2648958f * 0.05867535f;
        final float c = 0.8928169f * 0.7546882f;
        final float d = 0.0039135218f * 0.59395087f;
        final float e = 0.9114683f * 0.33522367f;

        System.out.println(a + b + c + d + e);
        System.out.println(a + b + c + e + d);
    }
}

关于java - Java HashMap 拷贝构造函数为什么会影响 float 精度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9624869/

相关文章:

java - 无法将 ClassCastException 对象强制转换为

java - 将菜单项或菜单添加到Java中的JTable列标题中

java - 导致异常的多个 Java 根本原因

c - 17位或更多位 double

c++ - 调用 placement new 时,将指针强制转换为 "void*"有什么影响吗?

c++ - 将为此代码运行复制构造函数吗?

c++ - ostringstream 和复制构造函数的问题

java - 如何使 Apache Camel Servlet 请求立即返回?

c++ - 最小/最大整数和 double

c - Labwindows 在添加 DOUBLE 数字时出现奇怪的行为