为什么是binaryw。格式在宽度58以上的行为有所不同?

时间:2016-01-25 19:11:09

标签: sas binary-data

考虑以下程序和输出:

data _null_;
input a;
length b $64;
do i = 1 to 64;
  fmtname = cats('binary',i);
  b = cats(putn(a,fmtname));
  put i= b=;
end;
cards;
1
;
run;

输出(SAS 9.1.3,Windows 7 x64):

i=1 b=1
i=2 b=01
i=3 b=001
i=4 b=0001
i=5 b=00001
/*Skipped a few very similar lines*/
i=58 b=0000000000000000000000000000000000000000000000000000000001
i=59 b=11111110000000000000000000000000000000000000000000000000000
i=60 b=111111110000000000000000000000000000000000000000000000000000
i=61 b=1111111110000000000000000000000000000000000000000000000000000
i=62 b=11111111110000000000000000000000000000000000000000000000000000
i=63 b=011111111110000000000000000000000000000000000000000000000000000
i=64 b=0011111111110000000000000000000000000000000000000000000000000000

Linux x64上SAS 9.4的最后几行输出:

 i=60 b=000000000000000000000000000000000000000000000000000000000001
 i=61 b=1111111110000000000000000000000000000000000000000000000000000
 i=62 b=11111111110000000000000000000000000000000000000000000000000000
 i=63 b=011111111110000000000000000000000000000000000000000000000000000
 i=64 b=0011111111110000000000000000000000000000000000000000000000000000

这种行为至少对我来说是意料之外的,并且似乎没有记录在help page上。它同意我发现here宽度为64的文档 - 标准双精度 - 但我不明白为什么它会在宽度59处翻转。

1 个答案:

答案 0 :(得分:1)

我得不到相同的结果 - 我的开关是61 - 但我相信答案是一样的。

直到某个点 - 58,60,在那里的某个地方 - SAS正在向您显示该数字的定点整数表示。用小数测试一下,如下:

data _null_;
a=3.14159265358979323846264338327950288419716939937510582;
length b $64;
put a= hex4.;
put a= hex8.;
put a= hex16.;
do i = 1 to 64;
  fmtname = cats('binary',i);
  b = cats(putn(a,fmtname));
  put i= b=;
end;
run;

你会得到一个令人惊讶的结果 - 你看到大多数行的000...0011,直到60.文档没有明确提到这一点,但它确实在示例中显示了它( 123.45和123在binary8.)中是相同的。

然后从61开始,或者59开始,我猜,你看到数字的实际表示,因为SAS内部存储它(或者,可以说,英特尔内部存储它的方式)。

二进制文档没有很好地解释这一点,但HEX.文档确实在一个提示中清楚地解释了它:

  

如果w< 16,HEXw。 format将实数二进制数转换为定点整数,然后将其写为十六进制字符。它还以二进制补码表示法写入负数,右对齐数字。如果w是16,HEXw。以十六进制形式显示浮点值。

Binary正在做同样的事情,在我的机器上它恰好发生在HEX也会做出改变 - 在15x4 = 60。 HEX.显示相同的信息 - 下面注明; hex4.hex8.显示的结果与hex16.不同。

要清楚,binary64.显示的值是正确的,而不是任何类型的截断(尽管61-63,在您的示例59-60中,左截断)。

我确实找到了一个SAS usage note,虽然它根据我们的测试明显过时了:

  

从SAS®V7开始,BINARYw。格式被改为与HEXw更加一致。格式。当HEXw。 format使用16的宽度(对应于8个字节的数据),它生成浮点值的十六进制表示。 BINARYw。格式已更改,因此宽度为57-64会生成浮点值的二进制表示,因为57-64的宽度对应于8个字节的数据。

它还包含如何获得整数的一致结果的建议,这可能是有用的。

  

BIN_64 = PUT(PUT(VALUE,S370FIB8),$ BINARY64);

S370FIB8.是一个format,它将数字转换为IBM Mainframe格式的固定整数二进制表示形式。 (即,它以Big-Endian格式写入整数,这不是您在Intel机器上获得的。)