Sas 在小数点的末尾删去一个数字

Sas 在小数点的末尾删去一个数字,sas,format,Sas,Format,我试图为每个记录添加一个值相同的变量。我创建了大约10个这样的变量(每个变量都有不同的值)。对于其中一个,SAS不保留最后一位数字(1)。我尝试调整格式使其更长,但它没有添加1,而是在右侧添加了额外的零 下面是代码示例: data createnewvars; set original; variable1=39.5652749413775; variable2=0.359365098601411; format variable1 17.13 variable2 18.15; ru

我试图为每个记录添加一个值相同的变量。我创建了大约10个这样的变量(每个变量都有不同的值)。对于其中一个,SAS不保留最后一位数字(1)。我尝试调整格式使其更长,但它没有添加1,而是在右侧添加了额外的零

下面是代码示例:

data createnewvars;
  set original;
  
variable1=39.5652749413775;
variable2=0.359365098601411;

format variable1 17.13 variable2 18.15;
run;
当我查看数据时,variable2的值=0.359365098601410。 仅供参考,当我缩短变量2的格式(例如17.13)值=0.3593650986014时,这是预期值


有什么办法解决这个问题吗?

首先:你的问题的实际答案;如果你感兴趣的话,那就谈谈数字是如何存储的

SAS能够很好地存储您显示的数字(或者,无论如何,已经足够好了),但它对您隐藏了一点精度,基本上是想表现得好一点——在失去实际精度之前,做15位小数的数学是很棘手的,因为您几乎没有空间

但是,有一个选项可以告诉SAS自己的行为并显示其全部功能。系统选项。默认情况下,它设置为COMPAT,这与较早版本的SAS保持一致;但是,如果您将其设置为stdiee,它将显示上述号码的所有数字。它不会向你展示更多,注意;你真的已经到了精度的极限了。这是添加的,所以如果您的营业场所仍有9.3或更早版本的应用程序,请不要使用它。该选项也可能被您的系统管理员锁定,因此,如果您在服务器环境中,并且您发现该选项不允许或不起作用,请与他们联系

请参见以下两个数据操作步骤:

options decimalconv=compat;
data _null_;
  variable2=0.35936509860141;
  variable3=0.359365098601411;
  put variable2= best18. / variable3= best18.;
run;

 variable2=0.35936509860141
 variable3=0.35936509860141

options decimalconv=stdieee;
data _null_;
  variable2=0.35936509860141;
  variable3=0.359365098601411;
  put variable2= best18. / variable3= best18.;
run;


 variable2=0.35936509860141
 variable3=0.359365098601411
与magic一样,variable3现在与您要求的额外1一起显示。但是,我无法强调,这不会影响变量中存储的内容;它只会影响它在屏幕上的显示方式(以及在其他任何地方使用它)——它在封面下总是相同的数字,并且它几乎是但不完全是你想要的,就像大多数浮点数一样。它也正处于精度的边缘,所以如果你用它做进一步的数学运算,“几乎但不完全”可能很重要。如果您需要如此高的精度,SAS可能不是您工作的理想语言


现在,解释一下这里发生了什么。SAS能够存储精度高达2^53的数字,这几乎是16位小数精度。然而,当您在精度极限上徘徊时,SAS往往显示不太整洁,因为与二的幂相关的舍入问题-因为数字存储在二进制中,所以存储精确的十进制数字就不太整洁,就像在十进制中存储“1/3”是不可行的。但数字仍然存在,仍然如此

在您的示例中,SAS确实以不同的方式存储这两个数字,尽管它不会以不同的方式显示它们。从您的示例扩展,请参见以下内容:

data createnewvars;

  
variable1=39.5652749413775;
variable2=0.35936509860141;
variable3=0.359365098601411;

put variable2= best18. / variable3= best18.;
put variable2= hex16. / variable3= hex16.;
put variable2= binary64. / variable3= binary64.;

equal = variable2 - variable3;
run;
这导致:

 variable2=0.35936509860141
 variable3=0.35936509860141
 variable2=3FD6FFD67874479F
 variable3=3FD6FFD6787447B1
 variable2=0011111111010110111111111101011001111000011101000100011110011111
 variable3=0011111111010110111111111101011001111000011101000100011110110001
请注意,十六进制表示在末尾略有不同。这是尾数的结尾,或者SAS存储的“精确”部分。(顺便说一句,这是假设您在Linux/Unix/Windows上运行;在IBM大型机上,这会有所不同,但在高级概念上类似。)事实上,当乘以两个适当的函数的不同幂时,它会相差约1x10-15-看看示例中的
equal
,这与这个数字非常接近,但我们稍后会讨论这个问题

不同的部分是最后6位数字:
011111
表示较短的数字,而
110001
表示较长的数字。这些数字分别乘以由数字的符号部分定义的二次幂,在这两种情况下都是
011111101
——十进制数字1021,然后被-1023偏移,最终结果为-2。这意味着第一个数字(二进制表示中的第13个数字)表示2-3,下一个数字表示2-4,依此类推

最后6位代表2-49到2-54<二进制代码>110001-011111为
010010
,即2-50加2-53。这两个数字加在一起并转换成十进制是9.99x10-16,或者正好是您忘记的1x10-15。另外,还记得上面SAS代码中的
equal
变量吗?看一看日志,它实际上等于这个


那么-为什么SAS不能显示最后一个数字?这是因为它不完全等于最后的1-并且它的关闭量小于SAS可以干净地存储的量(在您的示例中,小于2-54)。因此,SAS不想对您撒谎,说它能够安全、准确地存储数据,因此它向您隐瞒真相。

不确定这是否可能。@Reeza事实上这是可能的(如果可能不可取的话)。