Floating point 反复规范化IEEE浮点向量会使其发生变化吗?

Floating point 反复规范化IEEE浮点向量会使其发生变化吗?,floating-point,Floating Point,如果我取一个(非零)浮点向量(一个(x,y,z)向量),并将其规格化为单位长度,第二次规格化是否保证返回相同的结果?我不知道文献中的相关结果。快速测试表明,两次规范化3D向量通常会导致规范化向量和重新规范化向量之间的微小差异,即使在注意精确执行规范化(例如,通过使用更高精度的算术执行规范化)时也是如此。我使用下面的ISO-C99程序进行这个快速测试,在x64平台上使用编译器的“严格”浮点设置(icl/fp:strict)编译它 #包括 #包括 #包括 #包括 #包括 #定义使用_HYPOT(1)

如果我取一个(非零)浮点向量(一个
(x,y,z)
向量),并将其规格化为单位长度,第二次规格化是否保证返回相同的结果?

我不知道文献中的相关结果。快速测试表明,两次规范化3D向量通常会导致规范化向量和重新规范化向量之间的微小差异,即使在注意精确执行规范化(例如,通过使用更高精度的算术执行规范化)时也是如此。我使用下面的ISO-C99程序进行这个快速测试,在x64平台上使用编译器的“严格”浮点设置(
icl/fp:strict
)编译它

#包括
#包括
#包括
#包括
#包括
#定义使用_HYPOT(1)
//修正途径:格雷格·罗斯,吻:有点太简单了。http://eprint.iacr.org/2011/007
静态uint32_t z=362436069,w=521288629,jsr=362436069,jcong=123456789;
#定义znew(z=36969*(z&0xffff)+(z>>16))
#定义wnew(w=18000*(w&0xffff)+(w>>16))

#定义MWC((znewNo)不保证这一点。假设所有单精度浮点用于计算标准化,下面提供了一个反例:

#include <stdio.h>
#include <math.h>

void normalize(float a, float b, float c, float *outA, float *outB, float *outC)
{
    float norm = sqrtf (a*a+b*b+c*c);
    *outA = a / norm;
    *outB = b / norm;
    *outC = c / norm;
}

int main(void)
{
    float a =  -4.33681e-19;
    float b = -1.326157e-23;
    float c = 2.8502696e-20;

    float a1, b1, c1;
    normalize(a, b, c, &a1, &b1, &c1);

    float a2, b2, c2;
    normalize(a1, b1, c1, &a2, &b2, &c2);

    printf("Original        : (%a, %a, %a)\n", a,  b,  c);
    printf("Normalized      : (%a, %a, %a)\n", a1, b1, c1);
    printf("Twice normalized: (%a, %a, %a)\n", a2, b2, c2);
}

即使您使用双精度进行规范化,您仍然可以找到结果发生变化的反例。

我对此进行了研究,似乎您可以获得各种行为。对于下面的示例,我使用了

hypotf( a, hypotf( b,c ))
计算长度。 下表显示了三种Cordinate,然后是长度。 有时,最终会在两个值之间出现振荡:

    -0.000891105     0.402476907     0.915429652     0.999999881
    -0.000891105     0.402476966     0.915429771     0.999999881
    -0.000891105     0.402476907     0.915429652     1.000000119
    -0.000891105     0.402476966     0.915429771     0.999999881
    -0.000891105     0.402476907     0.915429652     1.000000119
    -0.000891105     0.402476966     0.915429771     0.999999881
    -0.000891105     0.402476907     0.915429652     1.000000119
    -0.000891105     0.402476966     0.915429771     0.999999881
    -0.000891105     0.402476907     0.915429652     1.000000119
    -0.000891105     0.402476966     0.915429771     0.999999881
    -0.000891105     0.402476907     0.915429652     1.000000119
有时你会有更复杂的行为:

 0.659812868     0.745291650     0.095850535     0.999999940
 0.659812927     0.745291710     0.095850542     0.999999940
 0.659812868     0.745291650     0.095850527     1.000000119
 0.659812927     0.745291710     0.095850535     0.999999940
 0.659812868     0.745291650     0.095850520     1.000000119
 0.659812927     0.745291710     0.095850527     0.999999940
 0.659812868     0.745291650     0.095850512     1.000000119
 0.659812927     0.745291710     0.095850520     0.999999940
 0.659812868     0.745291650     0.095850505     1.000000119
 0.659812927     0.745291710     0.095850512     0.999999940
 0.659812868     0.745291650     0.095850497     1.000000119
 0.659812927     0.745291710     0.095850505     0.999999940
 0.659812868     0.745291650     0.095850490     1.000000119
 0.659812927     0.745291710     0.095850497     0.999999940
 0.659812868     0.745291650     0.095850483     1.000000119
 0.659812927     0.745291710     0.095850490     0.999999940
 0.659812868     0.745291650     0.095850475     1.000000119
 0.659812927     0.745291710     0.095850483     0.999999940
 0.659812927     0.745291710     0.095850483     1.000000000
 0.659812927     0.745291710     0.095850483     1.000000000
 0.659812927     0.745291710     0.095850483     1.000000000

最好显示您用于规范化向量的代码。当您比较一组随机原始向量的规范化向量和重新规范化向量时,您观察到了什么?快速的特别测试似乎表明规范化向量和重新规范化向量之间的差异是常见的。标题和问题提出了相反的问题(向量是否会变异,向量是否会保持不变)。我建议更改其中一个。如果使用
hypot(hypot(a,b),c)
计算范数会怎么样?@aka。非常感谢您提出这一点,我应该将其作为替代代码路径。现在添加
hypot()
标准化向量和重新标准化向量之间的差异仍然很常见。
 0.659812868     0.745291650     0.095850535     0.999999940
 0.659812927     0.745291710     0.095850542     0.999999940
 0.659812868     0.745291650     0.095850527     1.000000119
 0.659812927     0.745291710     0.095850535     0.999999940
 0.659812868     0.745291650     0.095850520     1.000000119
 0.659812927     0.745291710     0.095850527     0.999999940
 0.659812868     0.745291650     0.095850512     1.000000119
 0.659812927     0.745291710     0.095850520     0.999999940
 0.659812868     0.745291650     0.095850505     1.000000119
 0.659812927     0.745291710     0.095850512     0.999999940
 0.659812868     0.745291650     0.095850497     1.000000119
 0.659812927     0.745291710     0.095850505     0.999999940
 0.659812868     0.745291650     0.095850490     1.000000119
 0.659812927     0.745291710     0.095850497     0.999999940
 0.659812868     0.745291650     0.095850483     1.000000119
 0.659812927     0.745291710     0.095850490     0.999999940
 0.659812868     0.745291650     0.095850475     1.000000119
 0.659812927     0.745291710     0.095850483     0.999999940
 0.659812927     0.745291710     0.095850483     1.000000000
 0.659812927     0.745291710     0.095850483     1.000000000
 0.659812927     0.745291710     0.095850483     1.000000000