gpt4 book ai didi

Java 不是确定性的?

转载 作者:搜寻专家 更新时间:2023-10-30 20:59:17 25 4
gpt4 key购买 nike

我用 Java 编写了一个小的捕食者-猎物模拟。即使规则非常复杂并最终形成一个困惑的系统,所使用的技术也很简单:

  • 基本数据类型的算术和决策
  • 没有外部库
  • 不包括外部系统
  • 没有并发发生
  • 不使用当前时间或日期

所以我想当用相同的参数初始化系统时它应该输出相同的结果,但事实并非如此,我想知道为什么。

一些想法:我的应用程序使用 Random,但对于那个测试,我用给定的值初始化它们,所以在我的理解中,它们应该为每次运行以相同的顺序创建相同的输出。

我正在遍历 Set,我知道 Set 的迭代顺序没有定义。但我看不出任何以相同顺序填充相同值的 Set 在多次运行中表现不同的原因。是吗?

我使用了很多float。我总是怀疑 1 + 1 = 1.9999999999725 的数据类型,但即使他们的行为对我来说很奇怪,它也应该总是一样的奇怪。不是吗?

垃圾收集不是确定性的,但只要我不依赖析构函数,我就应该是安全的。

上面说了,没有并发,也没有数据类型,要看实际使用时间。

我无法在一个简单的示例中重现该行为。但是通过我的代码,我看不到任何不可预测的东西。那么我上面的任何假设都是错误的吗?有什么我可能会遗漏的想法吗?

这里有一个测试来验证我的假设:

public static void main(String[] args) {
Random r = new Random(1);
Set<Float> s = new HashSet<Float>();
for (int i = 0; i < 1000000; i++) {
s.add(r.nextFloat());
}

float ret = 1;
int cnt = 0;
for (Float f : s) {
float multiply = 0.3f;
if (cnt++ % 2 == 0) {
multiply = 0.7f;
}
float f2 = (f * multiply);
ret += f2;
}

System.out.println(ret);
}

对我来说,结果总是 242455.25。

最佳答案

您可以用 Java 编写确定性程序。您只需要消除非确定性的可能来源。

如果不查看您的实际代码和该确定性的具体证据,就很难知道是什么导致了非确定性。

有许多库方法可能是非确定性行为的潜在来源……取决于您如何使用它们。

例如,Object.hashcode() 返回的值(第一次在实例上调用)是不确定的。这渗透到任何使用散列的库。当你迭代它们时,它肯定会影响 HashSetHashMap 的元素返回的顺序......如果元素类不覆盖 hashcode( )

随机数生成器可能是也可能不是确定性的。如果它们是伪随机的并且用固定的种子初始化,那么每个产生的数字序列将是确定的。

浮点运算应该是确定性的。对于算术表达式的任何(固定)输入集,结果应该始终相同。 (我不确定 JLS 是否保证浮点运算的确定性,但如果它在实践中发生,那将是非常奇怪的。就像......你在损坏的硬件上运行。)


FOLLOWUP ... strictfp 和非确定性。

根据JLS 15.4 :

"Within an expression that is not FP-strict, some leeway is granted for an implementation to use an extended exponent range to represent intermediate results; the net effect, roughly speaking, is that a calculation might produce "the correct answer" in situations where exclusive use of the float value set or double value set might result in overflow or underflow."

这并没有准确说明有多少实现在非 FP 严格表达式中的“回旋余地”。但是,我认为这种回旋余地不会扩展到允许非确定性行为。我原以为特定平台上的 JIT 编译器总是会为相同的表达式生成等效的 native 代码,并且该代码是确定性的。 (我看不出有任何非确定性的原因......除非硬件本身具有非确定性 float 。)非确定性的另一个可能来源可能是 JIT 编译和解释代码的行为可能不同。但坦率地说,我认为允许这种情况发生是“疯狂的”……而且我想我们早就听说过。

因此,虽然非 FP 严格的表达式评估在理论上可能是不确定的,但我认为我们应该对此打折扣……除非有明确的证据表明它在实践中发生。

(请注意,我说的是真正的非确定性,而不是平台差异。)

关于Java 不是确定性的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17626262/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com