【问题标题】:Fixed-sized float/double for portability固定大小的浮动/双精度,便于携带
【发布时间】:2016-10-15 21:48:37
【问题描述】:

我最近了解了固定大小的整数,并计划在我多年前编写的旧程序中使用它们。

float 和/或 double 是否有固定大小的 int 等效项?

我的计划是在程序的最大部分使用“本机类型”int,float,double,并且仅在考虑可移植性时(例如使用二进制文件读/写)指定固定大小的类型。 我使用二进制文件存储数据,例如:日期 yyyymmdd(所以 uint32)、标志 [0,4](所以 uint8)、字符串(以空结尾的字符串)和货币(现在是 @ 987654325@)。

关于可移植性,程序“可移植”是指它可以被编译(或交叉编译)并在不同平台上运行。到目前为止:linux、windows、android(本机,通过没有 GUI 的终端模拟器)和 OpenBSD(strcat/strcpy 只需要在 2 行中替换为 strlcat/strlcpy)。 如果我在 linux x86_64、android arm-something、windows 32 something 等之间使用相同的二进制数据文件,我担心存储的 float/double 会发生什么...我想拥有一种强制二进制文件中浮点值的唯一大小和表示的方法。

【问题讨论】:

  • 如果定义了__STDC_IEC_559__,则为是,否则为否。需要有关 FP 可移植性要求的更多详细信息。松散地:推荐将货币存储为字符串。
  • IEEE 浮点标准今天无处不在,除了一些非常便宜的嵌入式处理器。由于您正在阅读文件,因此可以忽略它们。您不能完全忽略的是字节顺序(又名 endiness),这也是您的固定大小整数的问题。
  • @chux:帖子已编辑以明确可移植性。
  • @Hans Passant:我从没想过endiness。我现在正在考虑将数据存储在纯文本文件中...
  • 对相关问题有帮助吗?

标签: c floating-point portability


【解决方案1】:

对于货币,建议特殊处理。选择一个固定宽度的整数类型以满足范围需求(int64_tint32_t)并按最小货币单位进行缩放。如果代码仅存储/读取值,例如 123.12

void Store_int32(int32_t x); // Handles int32_t in endian independent method
int32_t Get_int32(void);     // Handles int32_t in endian independent method

void Store_Currency(double c) {
  if (c < INT32_MIN/100.0 || c > INT32_MAX/100.0) Handle_RangeError();
  Store_int32(round(c*100.0));
}

double Get_Currency(void) {
  Get_int32()/100.0;
}

对于double 的一般用途,使用从文本十六进制(或具有足够精度的十进制)FP 表示法转换to/。

void Store_double(double c) {
  char s[100];
  sprintf(s, "%a", c);                         // 0x1.ec7ae147ae148p+6
  // or
  sprintf(s, "%.*e", DBL_DECIMAL_DIG - 1, c);  // 1.2312000000000000e+02
  Store_string(s);
}

double Get_double(void) {
  char s[100];
  Get_string(s, sizeof s);
  double x;
  sscanf(s, "%f", &x);  // %f reads decimal and hexadecimal FP formats.
  return x;
}

【讨论】:

  • 使用字符串似乎是存储数据最便携的解决方案。
【解决方案2】:

大多数浮点是 IEEE 754、64 位或 32 位。但是,如果您的处理器中的浮点单元不兼容,则没有现实、有效的方法使其兼容,因此程序在不同机器上运行时会产生略微不同的结果。 (这实际上是对健全程序的一个很好的测试——如果结果因浮点错误而有显着差异,那么你处理的浮点运算很糟糕)。

但是,您可以在二进制文件中加载和保存最接近 IEEE 754 的表示,可移植。代码在这里维护 here

【讨论】:

  • 如果主机使用非标准的浮点格式,那么该指令引入的重复舍入误差会使结果变得很糟糕。 github.com/MalcolmMcLean/ieee754/blob/… 使用整数计算会好得多,正如问题所指出的那样,stdint.h 中有固定大小的定义可以在任何兼容的平台上按预期工作,而不是依赖于假定不可靠。
  • @Pascal Cuoq:这是在科学计算的情况下,对吧?就我而言,我只存储短小数:123.12
  • 这取决于您的 FPU 是否可以准确地表示 0.5、0.25 等等。如果不是,则可能会严重累积错误。小数不能用二进制浮点数精确表示,但如果您只需要 5 个小数位,则该错误不太重要。
  • 就我而言,我猜是标准 CPU。你的回答回答了我的问题,但我发现我的问题也与终结有关。
猜你喜欢
  • 2018-07-09
  • 1970-01-01
  • 1970-01-01
  • 2011-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-06
相关资源
最近更新 更多