- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我用 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()
返回的值(第一次在实例上调用)是不确定的。这渗透到任何使用散列的库。当你迭代它们时,它肯定会影响 HashSet
或 HashMap
的元素返回的顺序......如果元素类不覆盖 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/
我使用 Deflater 编写了一个备份程序SHA-1 用于存储文件和哈希值。我看到Java的Deflater使用zlib 。如果我显式设置 Deflater 的级别,无论平台和 JRE 版本如何,我
考虑以下算法: r = 2 while r >= 1: x = -1 + 2 * random.random() y = -1 + 2 * random.random() r
我正在编写一个持久保存到磁盘的映射类。我目前只允许 str键,但如果我可以使用更多类型会很好:希望最多可以是任何可散列的(即与内置 dict 相同的要求),但更合理的是我会接受字符串、unicode、
我有一个不使用随机化的脚本,当我运行它时会给出不同的答案。我希望每次运行脚本时答案都是一样的。该问题似乎只发生在某些(病态)输入数据上。 该代码段来自一种计算线性系统特定类型 Controller 的
这对我来说不是问题,没有它我也可以生活,但我只是好奇这是否可能以及如何实现。 今天我了解到,scrapy.Request 不会按照启动的顺序完成。 伪代码示例: class SomeSpider(sc
我正在运行这个 SVD来自 scipy 的求解器,代码如下: import numpy as np from scipy.sparse.linalg import svds features = np
我正在尝试使用确定性 Miller-Rabin 算法实现素数检查功能,但结果并不总是正确的:在检查前 1,000,000 个数字时,它只找到 78,495 而不是 78,498。 这是使用 [2, 7
我正在审查各种 Android 声音 API,我想知道我应该使用哪一个。我的目标是获得低延迟的音频,或者至少是关于播放延迟的确定性行为。 我们遇到了很多问题,Android 声音 API 似乎很垃圾,
过去,我处理过对时间要求严格的软件开发。这些应用程序的开发基本上是这样进行的:“让我们编写代码,测试延迟和抖动,并优化它们,直到它们在可接受的范围内。”我觉得这非常令人沮丧。这不是我所说的 适当的工程
给定: SQL Server 表名为 TEST_TABLE TEST_TABLE 中名为 TEST_FIELD 的列 VARCHAR(50) NOT NULL 第 1 行:10YR3/6 第 2 行:
我在 64 位 Windows PC 上使用 Microsoft Visual Studio Community 2015,版本 14.xxx。 程序读取一个文本文件,其中每一行都是桥牌(四名玩家,每
我需要在 PHP 中创建一个可证明公平(确定性和种子)加密安全 (CS) 随机数生成器。我们正在运行 PHP 5,而 PHP 7 现在并不是一个真正的选择。但是,我找到了 PHP 7 的新 CS 函数
我是一名优秀的程序员,十分优秀!