计算小参数x(~10^-12)的1-sqrt(x),类似于expm1(在C/C++中)

计算小参数x(~10^-12)的1-sqrt(x),类似于expm1(在C/C++中),c++,c,math,precision,sqrt,C++,C,Math,Precision,Sqrt,我认为expm1函数适用于计算小x的1-expx,而不会因双精度约15位处截断1.0而损失精度。1-sqrtx有这样的函数吗?目前,我只是使用一个非常大的泰勒展开式,因为我需要尽可能多的精度数字,最好是所有的精度数字,因为double/long double可以提供 编辑:我严重混淆了我的意图:我希望计算10^-12和1之间的任意位置的x的1-sqrt1-x expm1函数适用于计算1-expx 如图所示: 对于较小的x值,expm1可能比expx-1更精确 1-sqrtx有这样的函数吗 不,至

我认为expm1函数适用于计算小x的1-expx,而不会因双精度约15位处截断1.0而损失精度。1-sqrtx有这样的函数吗?目前,我只是使用一个非常大的泰勒展开式,因为我需要尽可能多的精度数字,最好是所有的精度数字,因为double/long double可以提供

编辑:我严重混淆了我的意图:我希望计算10^-12和1之间的任意位置的x的1-sqrt1-x

expm1函数适用于计算1-expx

如图所示:

对于较小的x值,expm1可能比expx-1更精确

1-sqrtx有这样的函数吗

不,至少不在标准标题中

expm1函数适用于计算1-expx

如图所示:

对于较小的x值,expm1可能比expx-1更精确

1-sqrtx有这样的函数吗


不,至少不在标准标题中。

这里的问题似乎动机不好。当x为0时,expx收敛到1,这意味着给定相同的浮点精度,对于小x,expx-1的有效数字比expx的有效数字多,但对于sqrtx,情况并非如此,它在x为0时收敛到0。换句话说,对于小x,expx-1可以比expx精确一点点,但对于1-sqrtx,情况并非如此-事实上,这会变得更糟,因为你将它从接近0 1e-6的值带到接近1 0.99999的值


另一方面,如果您希望计算非常小的x的sqrt1+x,作为非常接近x=1的sqrtx的精确度量,那么sqrt1+x-1将是更精确的浮点计算。它的泰勒级数将非常有效;我发现,对于| x |<1e-9,x/2-x^2/8+x^3/16是sqrt1+x-1的一个很好的近似值,在3e-29的RMS分数误差范围内,边上的最大值为8e-29,是双精度的两倍。即使是二次近似也可能足够好,精度大约为20位

这里的问题似乎动机不好。当x为0时,expx收敛到1,这意味着给定相同的浮点精度,对于小x,expx-1的有效数字比expx的有效数字多,但对于sqrtx,情况并非如此,它在x为0时收敛到0。换句话说,对于小x,expx-1可以比expx精确一点点,但对于1-sqrtx,情况并非如此-事实上,这会变得更糟,因为你将它从接近0 1e-6的值带到接近1 0.99999的值


另一方面,如果您希望计算非常小的x的sqrt1+x,作为非常接近x=1的sqrtx的精确度量,那么sqrt1+x-1将是更精确的浮点计算。它的泰勒级数将非常有效;我发现,对于| x |<1e-9,x/2-x^2/8+x^3/16是sqrt1+x-1的一个很好的近似值,在3e-29的RMS分数误差范围内,边上的最大值为8e-29,是双精度的两倍。即使是二次近似也可能足够好,大约有20位精度

用于计算1-expx。。。然后你倒过来读:这是为了计算expx-1A,搜索SO会帮助你:double FoooDouble x{return 1-sqrtx;}怎么不足以满足你对小x的需求?@duffymo-那可能是因为我错提了这个问题。我是说1-sqrt1-x。我应该重新发布这个问题还是编辑这个问题?@zjw518一些库提供了一个函数sqrt1pm1来计算sqrtx+1-1,这应该适合您的目的,因为1-sqrt1-x=-sqrt1pm1-x。您可以自己创建一个合理的实现:double-sqrt1pm1 double a{returna/1.0+sqrt a+1.0;}用于计算1-expx。。。然后你倒过来读:这是为了计算expx-1A,搜索SO会帮助你:double FoooDouble x{return 1-sqrtx;}怎么不足以满足你对小x的需求?@duffymo-那可能是因为我错提了这个问题。我是说1-sqrt1-x。我应该重新发布这个问题还是编辑这个问题?@zjw518一些库提供了一个函数sqrt1pm1来计算sqrtx+1-1,这应该适合您的目的,因为1-sqrt1-x=-sqrt1pm1-x。您可以自己创建一个合理的实现:double sqrt1pm1 double a{return a/1.0+sqrt a+1.0;}或者,您可以使用x/sqrt1+x+1,它在代数上等同于sqrt1+x-1,但没有小x的取消工件。您是正确的,@jwimberley,我的意思是1-sqrt1-x。我的目的是要有一个函数,它适用于小到10^-12到1的x。在阅读了关于expm1的文章后,我把自己弄糊涂了,但我在这个问题的措辞上做得很糟糕。为了安全起见,我目前在扩展中有大约20个术语,因此我可以在x~.01处切换到使用sqrt-如果有一个函数封装这个术语,当然速度更快,那就太好了。虽然爸爸
尼尔的建议看起来很有希望。你可以根据你的目的修改我们的建议@DanielSchepler的可能更好:按照这个顺序计算-x/1+sqrt1-x。这等于x*1-sqrt1-x/1-1-x=1-sqrt1-x,但不依赖于取消来实现准确性。在上面的注释中,我的-x是一个打字错误,你可以使用x/sqrt1+x+1,它在代数上等同于sqrt1+x-1,但没有小x的取消工件。你是对的,@jwimberley,我的意思是1-sqrt1-x。我的目的是要有一个函数,它适用于小到10^-12到1的x。在阅读了关于expm1的文章后,我把自己弄糊涂了,但我在这个问题的措辞上做得很糟糕。为了安全起见,我目前在扩展中有大约20个术语,因此我可以在x~.01处切换到使用sqrt-如果有一个函数封装这个术语,当然速度更快,那就太好了。虽然丹尼尔的建议看起来很有希望。你可以根据你的目的修改我们的任何一个建议@DanielSchepler的可能更好:按照这个顺序计算-x/1+sqrt1-x。这等于x*1-sqrt1-x/1-1-x=1-sqrt1-x,但不依赖于取消来实现准确性。在上面的注释中,My-x输入了一个错误注释,即1-expx=-expm1x,因此expm1实际上非常适合此计算。您指出:这是另一种方式,我认为这与expm1是矛盾的。。适合于计算1-expx。我熟悉的问题是:不建议在第一杯咖啡之前发布:-注意1-expx=-expm1x,因此expm1实际上非常适合于此计算。您说过:这是另一种方式,我认为这与expm1是矛盾的。。适合计算1-expx。我熟悉的问题是:不建议在第一杯咖啡之前发布:-