数学中一个很奇怪的问题

发布于 2024-10-28 11:02:31 字数 492 浏览 1 评论 0原文

我在 mma v7.0 中这样做:

r[x_] := Rationalize[x, 0]; N[Nest[Sqrt, 10., 53] // r, 500]

它给了我 1.000000000000000222044604925031308084726333618164062500000000000000000

但是,如果我更进一步 N[Nest[Sqrt, 10., 54] // r, 500]

我得到的全是零。有谁知道解释,或者这是一个错误?

此外,看起来这种从解决方案 Nest[Sqrt, 10., 53] 中产生更多数字的方法效果不佳。如何获得此计算的更多有效数字?

非常感谢。

编辑

如果我执行Nest[Sqrt, 10., 50],我仍然得到很多有效数字。

I am doing this in mma v7.0:

r[x_] := Rationalize[x, 0];
N[Nest[Sqrt, 10., 53] // r, 500]

It gave me
1.000000000000000222044604925031308084726333618164062500000000000000000

However, if I go one step further
N[Nest[Sqrt, 10., 54] // r, 500]

I got all zeros. Does anybody know an explanation, or it is a bug?

Besides, looks like this way to produce more digits from the solution Nest[Sqrt, 10., 53] is not working very well. How to obtain more significant digits for this calculation?

Many thanks.

Edit

If I did Nest[Sqrt, 10., 50], I still got a lot of significant digits.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧话新听 2024-11-04 11:02:31

如果执行此操作 54 次,则除了零之外,没有任何有效数字。因此,您所做的合理化(仅保留位模式)给出了您所看到的。

InputForm[n53 = Nest[Sqrt, 10., 53]]

Out[180]//输入表单=
1.0000000000000002

InputForm[n54 = Nest[Sqrt, 10., 54]]

Out[181]//输入表单=
1.

Rationalize[n53, 0]

4503599627370497/4503599627370496

Rationalize[n54, 0]

Out[183]​​= 1

好奇的是:问题不在于迭代计算退化意义上的精度损失。事实上,迭代这些平方根实际上提高了精度。我们可以通过 bignum 输入看到这一点。

InputForm[n54 = Nest[Sqrt, 10.`20, 54]]

Out[188]//输入表单=
1.0000000000000001278191493200323453724568038240908339267044`36.25561976585499

这是实际的问题。当我们使用机器数字时,经过 54 次迭代后,得到的机器双精度数中除了零之外没有其他有效数字。也就是说我们对数量的大小限制就是原因。

原因并不算太神秘。将结果值称为 1+eps。然后我们有 (1+eps)^(2^54) 等于(接近近似)10。然后二阶展开表明 eps 必须小于机器 epsilon。

InputForm[epsval = 

首先[选择[
每股收益/。 N[求解[Sum[eps^j*二项式[2^54, j], {j, 2}] == 9, eps]],
Head[#] === Real && #> 0 &]]]
Out[237]//输入表单=
1.864563472253985*^-16

$MachineEpsilon

输出[235]= 2.22045*10^-16

丹尼尔·利希布劳
沃尔夫勒姆研究公司

You have no significant digits other than zeros if you do this 54 times. Hence rationalizing as you do (which simply preserves bit pattern) gives what you saw.

InputForm[n53 = Nest[Sqrt, 10., 53]]

Out[180]//InputForm=
1.0000000000000002

InputForm[n54 = Nest[Sqrt, 10., 54]]

Out[181]//InputForm=
1.

Rationalize[n53, 0]

4503599627370497/4503599627370496

Rationalize[n54, 0]

Out[183]= 1

For the curious: the issue is not loss of precision in the sense of degradation with iterations computation. Indeed, iterating these square roots actually increases precision. We can see this with bignum input.

InputForm[n54 = Nest[Sqrt, 10.`20, 54]]

Out[188]//InputForm=
1.0000000000000001278191493200323453724568038240908339267044`36.25561976585499

Here is the actual problem. When we use machine numbers then after 54 iterations there are no significant digits other than zeros in the resulting machine double. That is to say, our size restriction on the numbers is the cause.

The reason is not too mysterious. Call the resulting value 1+eps. Then we have (1+eps)^(2^54) equal (to close approximation) to 10. A second order expansion then shows eps must be smaller than machine epsilon.

InputForm[epsval = 

First[Select[
eps /. N[Solve[Sum[eps^j*Binomial[2^54, j], {j, 2}] == 9, eps]],
Head[#] === Real && # > 0 &]]]
Out[237]//InputForm=
1.864563472253985*^-16

$MachineEpsilon

Out[235]= 2.22045*10^-16

Daniel Lichtblau
Wolfram Research

我家小可爱 2024-11-04 11:02:31
InputForm /@ NestList[Sqrt, 10., 54]

10.
3.1622776601683795
1.7782794100389228
1.333521432163324
1.1547819846894583
1.0746078283213176
1.036632928437698
1.018151721718182
1.0090350448414476
1.0045073642544626
1.002251148292913
1.00112494139988
1.0005623126022087
1.00028111678778
1.0001405485169472
1.0000702717894114
1.000035135277462
1.0000175674844227
1.0000087837036347
1.0000043918421733
1.0000021959186756
1.000001097958735
1.0000005489792168
1.0000002744895706
1.000000137244776
1.0000000686223856
1.000000034311192
1.0000000171555958
1.0000000085777978
1.0000000042888988
1.0000000021444493
1.0000000010722245
1.0000000005361123
1.0000000002680562
1.0000000001340281
1.000000000067014
1.000000000033507
1.0000000000167535
1.0000000000083769
1.0000000000041884
1.0000000000020943
1.0000000000010472
1.0000000000005236
1.0000000000002618
1.000000000000131
1.0000000000000655
1.0000000000000329
1.0000000000000164
1.0000000000000082
1.000000000000004
1.000000000000002
1.0000000000000009
1.0000000000000004
1.0000000000000002
1.

在上面扔 N[x, 500] 就像试图从岩石中挤出水一样。


上面的计算是在机器精度下完成的,速度非常快。如果您愿意放弃速度,您可以利用 Mathematica 的任意精度算术指定输入值的非机器精度。可以使用“反引号”来执行此操作(如下例所示),或者您可以使用 SetPrecisionSetAccuracy 。这里我将指定输入是10到20位精度的数字。

NestList[Sqrt, 10`20, 54]

10.000000000000000000
3.1622776601683793320
1.77827941003892280123
.
.
.
1.00000000000000051127659728012947952
1.00000000000000025563829864006470708
1.000000000000000127819149320032345372

正如您所看到的,您不需要使用 InputForm,因为 Mathematica 会自动将任意精度的数字打印到尽可能多的位置。

如果您确实使用 InputFormFullForm,您将看到一个反引号,然后是一个数字,这是该数字的当前精度。

InputForm /@ NestList[Sqrt, 10., 54]

10.
3.1622776601683795
1.7782794100389228
1.333521432163324
1.1547819846894583
1.0746078283213176
1.036632928437698
1.018151721718182
1.0090350448414476
1.0045073642544626
1.002251148292913
1.00112494139988
1.0005623126022087
1.00028111678778
1.0001405485169472
1.0000702717894114
1.000035135277462
1.0000175674844227
1.0000087837036347
1.0000043918421733
1.0000021959186756
1.000001097958735
1.0000005489792168
1.0000002744895706
1.000000137244776
1.0000000686223856
1.000000034311192
1.0000000171555958
1.0000000085777978
1.0000000042888988
1.0000000021444493
1.0000000010722245
1.0000000005361123
1.0000000002680562
1.0000000001340281
1.000000000067014
1.000000000033507
1.0000000000167535
1.0000000000083769
1.0000000000041884
1.0000000000020943
1.0000000000010472
1.0000000000005236
1.0000000000002618
1.000000000000131
1.0000000000000655
1.0000000000000329
1.0000000000000164
1.0000000000000082
1.000000000000004
1.000000000000002
1.0000000000000009
1.0000000000000004
1.0000000000000002
1.

Throwing N[x, 500] on this is like trying to squeeze water from a rock.


The calculations above are done in machine precision, which is very fast. If you are willing to give up speed, you can utilize Mathematica's arbitrary precision arithmetic by specifying a non-machine precision on the input values. The "backtick" can be used to do this (as in the example below) or you can use SetPrecision or SetAccuracy. Here I will specify that the input is the number 10 up to 20 digits of precision.

NestList[Sqrt, 10`20, 54]

10.000000000000000000
3.1622776601683793320
1.77827941003892280123
.
.
.
1.00000000000000051127659728012947952
1.00000000000000025563829864006470708
1.000000000000000127819149320032345372

As you can see you do not need to use InputForm as Mathematica will automatically print arbitrary-precision numbers to as many places as it accurately can.

If you do use InputForm or FullForm you will see a backtick and then a number, which is the current precision of that number.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文