Floating point 截断浮点值是否会产生其他错误?(AS3)
我试图构建一个确定性模拟,通过以下函数截断浮点数: (我在这里找到的:) 我的问题是:我将它除以10000,这一事实本身不是浮点错误的来源吗? 也就是说,每次分割发生时,都会产生一个新的浮动,并可能产生更多不确定的结果 编辑: 这个怎么样?仅使用2的幂Floating point 截断浮点值是否会产生其他错误?(AS3),floating-point,truncate,deterministic,Floating Point,Truncate,Deterministic,我试图构建一个确定性模拟,通过以下函数截断浮点数: (我在这里找到的:) 我的问题是:我将它除以10000,这一事实本身不是浮点错误的来源吗? 也就是说,每次分割发生时,都会产生一个新的浮动,并可能产生更多不确定的结果 编辑: 这个怎么样?仅使用2的幂 return Math.round(float* 1024) / 1024; 当你说确定性时,我假设你想要一个可再现的模拟,每次运行模拟时都会得到完全相同的结果 要做到这一点,您需要找到可能的变化源并消除它 唯一的方法是编译为特定体系结构的二进
return Math.round(float* 1024) / 1024;
当你说确定性时,我假设你想要一个可再现的模拟,每次运行模拟时都会得到完全相同的结果 要做到这一点,您需要找到可能的变化源并消除它 唯一的方法是编译为特定体系结构的二进制文件 浮点运算本身是完全指定的。所有现代处理器都遵循浮点标准(IEEE-754),不存在歧义 主要有两种变化:
(a+b)+c
和a+(b+c)
是等价的(加法是关联的)。在浮点计算中,情况并非如此。如果a
是一,b
是负一,c
是一个很小的数字,使得1+c
四舍五入到1
,那么表达式分别计算为c
和0
。编译器决定使用哪些指令。根据您的语言和平台,它可能是语言编译器或即时IL/字节码编译器。无论哪种方式,编译器都是一个黑盒子,它可能会在我们不知情的情况下改变编译代码的方式。最小的差异可能导致不同的最终结果a
位,然后舍入到b(
位并不等于从一开始舍入到b
位。例如:1.49四舍五入到一位为1.5,四舍五入到零位为2。但四舍五入到零位数直接得到1
因此,在基于x87的系统上,使用80位“扩展”精度作为中间值,从64位有效位开始。您可以直接将其四舍五入到所需的精度。如果有双精度中间值,则得到相同的中间结果,但四舍五入到53个有效位,然后四舍五入到所需的精度
您唯一的选择是为特定的体系结构生成机器代码
现在,如果您的目标只是最小化差异,而不是完全消除差异,那么答案很简单:除以或乘以二的幂(如1024)不会在应用程序使用的范围内引入任何额外的舍入误差,而乘以或除以数字(如1000)则会引入任何额外的舍入误差
如果将累积误差视为随机游动,那么使用1000进行舍入比使用1024进行舍入需要更多的步骤。乘法和除法都可能引入额外的错误。因此,平均而言,总误差将更大,因此舍入操作出错的可能性更大。当你对每个操作进行取整时,这甚至是正确的。当你说确定性时,我假设你想要一个可再现的模拟,每次运行模拟时都会得到完全相同的结果 要做到这一点,您需要找到可能的变化源并消除它 唯一的方法是编译为特定体系结构的二进制文件 浮点运算本身是完全指定的。所有现代处理器都遵循浮点标准(IEEE-754),不存在歧义 主要有两种变化:
(a+b)+c
和a+(b+c)
是等价的(加法是关联的)。在浮点计算中,情况并非如此。如果a
是一,b
是负一,c
是一个很小的数字,使得1+c
四舍五入到1
,那么表达式分别计算为c
和0
。编译器决定使用哪些指令。根据您的语言和平台,它可能是语言编译器或即时IL/字节码编译器。无论哪种方式,编译器都是一个黑盒子,它可能会在我们不知情的情况下改变编译代码的方式。最小的差别可以忽略不计
return Math.round(float* 1024) / 1024;
Machine 0 produces 0x1p+0 (1).
Machine 1 produces 0x1.004p+0 (1.0009765625).
The results differ.
#include <stdio.h>
#include <math.h>
// Round a value to the nearest multiple of the quantum.
static double Quantize(double x)
{
static const double Quantum = 1024., InverseQuantum = 1/Quantum;
return round(x * Quantum) * InverseQuantum;
}
int main(void)
{
/* For this example, we are in the middle of some calculation, where we
have some value a from earlier operations. a0 and a1 represent the
calculated values of a on two different platforms. Observe that the
difference is as small as possible, just a single ULP.
*/
double a0 = 0x1.cbd9f42000000p0;
double a1 = 0x1.cbd9f42000001p0;
// Define a constant that the calculation uses.
double b = 0x1.1d2b9fp-1;
// Calculate the pre-quantization result on each machine.
double x0 = a0 * b;
double x1 = a1 * b;
// Quantize the result on each machine.
double y0 = Quantize(x0);
double y1 = Quantize(x1);
// Display the results.
printf("Machine 0 produces %a (%.53g).\n", y0, y0);
printf("Machine 1 produces %a (%.53g).\n", y1, y1);
printf("The results %s.\n", y0 == y1 ? "are identical" : "differ");
return 0;
}
Math.round(1024 * float) / 1024;