IEEE754 单精度浮点数的字节表示不一致

问题描述 投票:0回答:1

当使用 Common Lisp 读取包含单精度浮点二进制编码的数据文件(可能是由 C/C++ 编写)时,会出现此问题。在 Lisp 中,我使用了

ieee-floats
包中的 decode-float32。然而,这导致浮点数的有效数与 C 程序读取相同浮点数时所读取的浮点数略有不同。

从表面上看,

ieee-floats:decode-float32
的代码似乎忠实于维基百科页面中对IEEE754单浮点数的描述。此外,这个在线 IEEE-754 Floating Point Converter 与该行为一致。

所以有两个问题。为什么C版本不一致?如何在 Lisp 中复制 C 行为?

这一切都是在 x86_64 GNU/Linux 上使用最新版本的 sbcl、gcc 和 clang 进行的。

下面是我用来实验和确认行为的一些代码。

这里有一些 C 代码,用于生成一些随机浮点数及其字节表示形式

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

int COUNT = 16;

void main () {
  float f;
  uint32_t i;
  char* pf = (char *)&f;
  char* pi = (char *)&i;

  for(int j=0; j<COUNT; j++) {
    f = (float)rand()/(float)(RAND_MAX/2.0) - 1.0;
    pf = (char *)&f;
    pi = (char *)&i;
    memcpy(pi, pf, sizeof(float));
    printf("%9f #x%x\n", f, i);
  }
}

这里有一些 Lisp 代码来读取这些浮点数和字节,并将 Lisp 编码与 C 编码进行比较。

(ql:quickload '(:iterate :ieee-floats))

(defun scan (&optional (file "floats_and_bytes.dat"))
  (with-open-file (in file)
    (iter (for f next (read in nil))
          (for b next (read in nil))
          (while (and f b))
          (format t "~9f ~x ~x ~b~%"
                  f
                  (ieee-floats:encode-float32 f)
                  b
                  (- (ieee-floats:encode-float32 f) b)))))
c floating-point common-lisp ieee-754
1个回答
1
投票

常见

float
具有 24 位二进制有效数,最多需要 9 个有效十进制数字 才能唯一打印
float
值(以及符号和指数)。

printf("%9f #x%x\n", f, i);
使用总共 9 个字符打印 (-1.0 ... + 1.0) 范围内的值:
' '
'-'
'0'
'.'
,6 位数字。这最多是 6 位有效数字。


建议的更改(以及一些小的 C 改进):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

int COUNT = 16;

int main() {
  union {
    float f;
    uint32_t i;
  } x;

  for (int j = 0; j < COUNT; j++) {
    x.f = (float) rand() / ((float) (RAND_MAX /2 + 1)) - 1.0f;
    printf("% .9g #x%lx\n", x.f, (unsigned long) x.i);
  }
}

样本输出

 0.380002022 #x3ec28fa0
 0.0108368397 #x3c318d00  // 10 digits after the '.', yet 9 significant digits.
 0.182981133 #x3e3b5f68
 0.109569788 #x3de06620
-0.243142366 #xbe78fa50
-0.484535754 #xbef81512
-0.585235715 #xbf15d202
 0.252523899 #x3e814ad0
-0.319745898 #xbea3b5bc
 0.687703729 #x3f300d5a
-0.862443924 #xbf5cc920
-0.180186212 #xbe3882bc
 0.75998807 #x3f428e94
-0.3610394 #xbeb8da28
 0.961136341 #x3f760d08
-0.829990387 #xbf547a40
© www.soinside.com 2019 - 2024. All rights reserved.