为什么在 SAS 中,科学计数法中的数字文字给出的数字与显式写出的数字不同?

发布于 2024-07-19 17:43:38 字数 1371 浏览 7 评论 0原文

以下 SAS 代码:

data _null_;
  format t u best32.;
  t = 10000000000000000000000000;
  u = 1e25;
  put t u;
  if t ne u then put 'diff';
run;

在我的 Windows 计算机上打印出:

10000000000000000905969664 9999999999999998758486016
diff

虽然我知道只有前 15-16 位数字是可信的,但为什么它们给出不同的基础数字呢? SAS 计算 1e25 怎么样?

编辑:我被要求提供 10 到 1e25 的其他幂的输出。 以下程序:


%macro doit;
data _null_;
  format t u best32.;
%let t=1;
%do i=1 %to 25;
  %let t=&t.0;
  t = &t;
  u = 1e&i;
  put t u;
%end;
run;
%mend;
%doit;

给出以下输出:


10 10
100 100
1000 1000
10000 10000
100000 100000
1000000 1000000
10000000 10000000
100000000 100000000
1000000000 1000000000
10000000000 10000000000
100000000000 100000000000
1000000000000 1000000000000
10000000000000 10000000000000
100000000000000 100000000000000
1000000000000000 1000000000000000
10000000000000000 10000000000000000
100000000000000000 100000000000000000
1000000000000000000 1000000000000000000
10000000000000000000 10000000000000000000
100000000000000000000 100000000000000000000
1000000000000000000000 1000000000000000000000
10000000000000000000000 10000000000000000000000
99999999999999991611392 99999999999999991611392
999999999999999983222784 999999999999999983222784
10000000000000000905969664 9999999999999998758486016

The following SAS code:

data _null_;
  format t u best32.;
  t = 10000000000000000000000000;
  u = 1e25;
  put t u;
  if t ne u then put 'diff';
run;

on my Windows machine prints out:

10000000000000000905969664 9999999999999998758486016
diff

While I understand that only the first 15-16 digits are to be trusted, why do they give different underlying numbers at all? How is SAS computing 1e25?

Edit: I've been asked to give the output for other powers of 10 up to 1e25. The following program:


%macro doit;
data _null_;
  format t u best32.;
%let t=1;
%do i=1 %to 25;
  %let t=&t.0;
  t = &t;
  u = 1e&i;
  put t u;
%end;
run;
%mend;
%doit;

gives the following output:


10 10
100 100
1000 1000
10000 10000
100000 100000
1000000 1000000
10000000 10000000
100000000 100000000
1000000000 1000000000
10000000000 10000000000
100000000000 100000000000
1000000000000 1000000000000
10000000000000 10000000000000
100000000000000 100000000000000
1000000000000000 1000000000000000
10000000000000000 10000000000000000
100000000000000000 100000000000000000
1000000000000000000 1000000000000000000
10000000000000000000 10000000000000000000
100000000000000000000 100000000000000000000
1000000000000000000000 1000000000000000000000
10000000000000000000000 10000000000000000000000
99999999999999991611392 99999999999999991611392
999999999999999983222784 999999999999999983222784
10000000000000000905969664 9999999999999998758486016

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

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

发布评论

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

评论(1

梦在深巷 2024-07-26 17:43:38

看起来它实际上可能正在计算 1 * 10 * 10 ... * 10 并且一旦超出基础浮点类型的有效位数,错误就会悄悄出现。

但我不认为 IEE754 类型的 float/double 会发生这种情况,因为它完全能够表示 1x10全范围 而不会损失精度。

一种可能性是,您遇到的问题与存储精度低于允许的浮点数的能力有关(这可能会搞砸 1e25 计算) - 请参阅 http://www.uc.edu/sashtml/lrcon/z0695157.htm#z0695187 获取解释。

更新 1:

好的,根据您的评论,您没有限制长度。 下面的代码给了你什么?

t = 10;
u = 1e1;
put t u;
t = 100;
u = 1e2;
put t u;
t = 1000;
u = 1e3;
put t u;
: : :
t = 10000000000000000000000000;
u = 1e25;
put t u;

根据该输出,我们或许可以推断出幕后发生的事情。

It looks like it might actually be calculating 1 * 10 * 10 ... * 10 and the errors are creeping in as soon as you get beyond the significant number of bits for the underlying float type.

But I don't believe that would happen for an IEE754 type float/double since it's quite able to represent 1x10full-range without loss of precision.

One possibility is that the problem you are having is related to the ability to store floats with less precision than allowed (which could possibly screw up a 1e25 calculation) - see http://www.uc.edu/sashtml/lrcon/z0695157.htm#z0695187 for an explanation.

Update 1:

Okay, so based on your comment, you're not restricting the length. What does the following code give you?

t = 10;
u = 1e1;
put t u;
t = 100;
u = 1e2;
put t u;
t = 1000;
u = 1e3;
put t u;
: : :
t = 10000000000000000000000000;
u = 1e25;
put t u;

Based on that output, we can probably deduce what's going on under the covers.

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