我在Java中实现了Kahan floating point summation algorithm。我想将它与Java中的内置浮点加法和Mathematica中的无限精度加法进行比较。但是我的数据集不适合测试,因为数字彼此接近。 (条件号〜= 1)
在我的数据集上运行Kahan会得到与内置+
最相同的结果。
有人可以建议如何生成大量可能导致严重舍入错误的数据吗?
答案 0 :(得分:1)
然而,我所拥有的数据集不适合测试,因为数字彼此接近。
听起来你已经知道问题是什么了。得到它=)
您需要一些东西:
为了让你开始,你可以尝试一些简单的三项和,这应该清楚地显示效果:
1.0 + 1.0e-20 - 1.0
通过简单求和进行评估,这将给出0.0
;明显不正确。您还可以查看表单的总和:
a0 + a1 + a2 + ... + an - b
b
是天真评估的总和a0 + ... + an
。
答案 1 :(得分:0)
你想要一堆高精度数字吗?试试这个:
double[] nums = new double[SIZE];
for (int i = 0; i < SIZE; i++)
nums[i] = Math.rand();
答案 2 :(得分:0)
我们是在谈论数字对还是序列?
如果成对,则从两个数字的1开始,然后在每次迭代中将1除以3,将另一个乘以3.可以很容易地计算这些对的理论总和,并且您将获得一大堆舍入误差。 (一些来自分部,一些来自加法。如果你不想要除法错误,那么用2而不是3。)
答案 3 :(得分:0)
通过实验,我发现了以下模式:
public static void main(String[] args) {
System.out.println(1.0 / 3 - 0.01 / 3);
System.out.println(1.0 / 7 - 0.01 / 7);
System.out.println(1.0 / 9 - 0.001 / 9);
}
我减去了素数的近似负幂(它不应该具有二进制形式的精确表示)。但是,有些情况下,这样的表达式会正确评估,例如
System.out.println(1.0 / 9 - 0.01 / 9);
你可以通过迭代减数的幂来自动化这种方法,并在乘以适当的值时停止产生整数,例如:
System.out.println((1.0 / 9 - 0.001 / 9) * 9000);
if (1000 - (1.0 / 9 - 0.001 / 9) * 9000 > 1.0)
System.out.println("Found it!");
答案 4 :(得分:0)
Scalacheck可能适合您。这是一个简短的样本:
cat DoubleSpecification.scala
import org.scalacheck._
object DoubleSpecification extends Properties ("Doubles") {
/*
(a/1000 + b/1000) = (a+b) / 1000
(a/x + b/x ) = (a+b) / x
*/
property ("distributive") = Prop.forAll { (a: Int, b: Int, c: Int) =>
(c == 0 || a*1.0/c + b*1.0/c == (a+b) * 1.0 / c) }
}
object Runner {
def main (args: Array[String]) {
DoubleSpecification.check
println ("...done")
}
}
要运行它,你需要scala和schalacheck-jar。我使用的是2.8版本(我不必说,你的c-path会有所不同):
scalac -cp /opt/scala/lib/scalacheck.jar:. DoubleSpecification.scala
scala -cp /opt/scala/lib/scalacheck.jar:. DoubleSpecification
! Doubles.distributive: Falsified after 6 passed tests.
> ARG_0: 28 (orig arg: 1030341)
> ARG_1: 9 (orig arg: 2147483647)
> ARG_2: 5
Scalacheck采用一些随机值(orig args)并尝试简化这些,如果测试失败,以便找到简单的例子。