Glsl WebGL:exp()非常不准确

Glsl WebGL:exp()非常不准确,glsl,webgl,webgl2,Glsl,Webgl,Webgl2,我只是把数字从1循环到50,然后打印出WebGL的exp(float)计算结果。我使用的是来自WebGL2的highp精度 precision highp float; varying vec2 TexCoords; uniform highp sampler2D A; void main() { float result = exp(texture2D(A, TexCoords).r); gl_FragColor.r = result;

我只是把数字从1循环到50,然后打印出WebGL的exp(float)计算结果。我使用的是来自WebGL2的highp精度

   precision highp float;
    varying vec2 TexCoords;
    uniform highp sampler2D A;

    void main() {
      float result = exp(texture2D(A, TexCoords).r);
      gl_FragColor.r = result;
    }
我用javascript运行了同样的程序,并比较了结果。聪明的事物非常小,但很快就会累积成非常大的数字

所以我还比较了javascript和python(numpy)的结果,它们非常相似

以下是Math.abs(diff)中的lat数字:

差异“,8.25484005595456e-8, 3.700182968913168e-7, 0.0000037810978241736848, 0.0000055018942362039525, 0.000003128868712565236, ... 12720537652, 21883728284, 30738633104, 20683268800, 324543434496, 2989835245824, 6539001840640, 12329169293312, 110431739568128, 262788127178752, 615023709454336, 13695288830853123028196912005120

这些是javascript和pyton之间的最后几个区别 :

3.0517578125e-05 6.10351562E-05 0 0.0 ... 0 0 0 0 0 32 0 0.0 ... 0 0 0 262144.0

以下是WebGL计划的前几个数字:

“来自WebGL的结果”, '2.7182817459106445,7.3890557289123535,20.08553314289844

从javascript:

“来自javascript的结果”, '2.718281828459045,7.38905609893065,20.085536923187668


不是WebGL用户,所以我可能错了,但您的差异表明WebGL只有前
6-7位是正确的。对于
32位
float精度(仅尾数的
23位
)来说,这听起来是正确的

javascript结果在前16位是正确的,对应于
64位
double
,因此您最有可能比较
32位
64位
的计算,因此其精确度较低也就不足为奇了

以下是比较:

WebGL     : 2.7182817459106445 ,7.3890557289123535 ,20.085533142089844  ,
javascript: 2.718281828459045  ,7.38905609893065   ,20.085536923187668  ,
PI float  : 2.71828174591064453,7.38905572891235352,20.08553504943847656,
PI double : 2.71828182845904509,7.38905609893064952,20.08553692318766437,
x87 double: 2.7182818284590451 ,7.3890560989306504 ,20.0855369231876679 ,
前两行是你的号码。
PI
行由
e
常数乘以
32bit
64bit
上的x87计算得出。最后一行使用x87 FPU内部
e^x
实现
80位->64位


正如你所看到的,WebGL
32位
的相关性非常紧密地支持了我的结论。

不是WebGL用户,所以我可能是错的,但你的差异表明WebGL只有前
6-7位是正确的。对于
32位
float精度(仅尾数的
23位
)来说,这听起来是正确的

javascript结果在前16位是正确的,对应于
64位
double
,因此您最有可能比较
32位
64位
的计算,因此其精确度较低也就不足为奇了

以下是比较:

WebGL     : 2.7182817459106445 ,7.3890557289123535 ,20.085533142089844  ,
javascript: 2.718281828459045  ,7.38905609893065   ,20.085536923187668  ,
PI float  : 2.71828174591064453,7.38905572891235352,20.08553504943847656,
PI double : 2.71828182845904509,7.38905609893064952,20.08553692318766437,
x87 double: 2.7182818284590451 ,7.3890560989306504 ,20.0855369231876679 ,
前两行是你的号码。
PI
行由
e
常数乘以
32bit
64bit
上的x87计算得出。最后一行使用x87 FPU内部
e^x
实现
80位->64位


正如你所看到的,WebGL
32位的相关性
浮动非常紧密地支持我的结论。

你说的很有道理。我回去尝试使用Float32Array迫使javascript提供更兼容的答案,但这并没有带来多大区别。我也用pow(e,x)来代替,结果并没有任何改善。我们只能照原样去做。@JeffSaremi在PC上通常使用x87 FPU,其内部数字表示为80位,因此即使在32位浮点上使用exp,也会使用80位指令,结果会被截断为32位格式。在GPU上只有32位(甚至更少),因此exp本身的精度比80位要低。如果你想检查差异计算
e^x
你自己喜欢的
(result=1.0,i=0;我你说的很有道理。我回去尝试使用Float32Array来强制javascript得出更兼容的答案,但没有多大区别。我还使用了pow(e,x)取而代之的是,结果并没有任何改善。我们只能照原样来处理。@JeffSaremi在PC上通常使用x87 FPU,其内部数字表示为80位,因此即使在32位浮点上使用exp,也会使用80位指令,结果被截断为32位格式。在GPU上,只有32位(甚至更少)因此exp本身与80位相比精度较低。如果您想检查差异compute
e^x
您自己的
(result=1.0,i=0;i