固定大小 float/double 便于携带
Fixed-sized float/double for portability
我最近了解了固定大小的整数,并计划在我多年前编写的旧程序中使用它们。
float and/or double 是否有固定大小的 int 等价物?
我的计划是将 "native types" int,float,double
用于程序的大部分,并且仅在考虑可移植性时才指定固定大小的类型(例如 read/write 二进制文件).
我使用二进制文件存储数据,如:date yyyymmdd (so uint32
), flags [0,4] (so uint8
), string (null terminated string ) 和货币(现在是 double
)。
关于可移植性,程序"portable"是可以在不同平台上编译(或交叉编译)和运行的意义。到目前为止:linux、windows、android(本机,通过没有 GUI 的终端仿真器)和 OpenBSD(strcat/strcpy 只需要替换为 strlcat/strlcpy 2 行)。
我担心如果我在 linux x86_64、android arm-something、windows 32 之间使用相同的二进制数据文件,存储的 float/double 会发生什么某事,等等...我希望有一种方法可以在二进制文件中强制执行浮点值的唯一大小和表示。
大多数浮点是 IEEE 754、64 位或 32 位。然而,如果你的处理器中的浮点单元不兼容,就没有现实有效的方法让它兼容,因此当 运行 在不同的机器上时,程序会产生略微不同的结果。 (这实际上是对声音程序的一个很好的测试 - 如果由于浮点错误导致结果显着不同,那么你处理的浮点运算很糟糕)。
但是,您可以在二进制文件中以可移植的方式加载和保存最接近 IEEE 754 的表示形式。代码在这里维护 here
对于货币,建议进行特殊处理。 Select 一种固定宽度的整数类型,以满足范围需求(int64_t
或 int32_t
)并按最小货币单位缩放。如果代码只有 storing/reading 个值,例如 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;
}
我最近了解了固定大小的整数,并计划在我多年前编写的旧程序中使用它们。
float and/or double 是否有固定大小的 int 等价物?
我的计划是将 "native types" int,float,double
用于程序的大部分,并且仅在考虑可移植性时才指定固定大小的类型(例如 read/write 二进制文件).
我使用二进制文件存储数据,如:date yyyymmdd (so uint32
), flags [0,4] (so uint8
), string (null terminated string ) 和货币(现在是 double
)。
关于可移植性,程序"portable"是可以在不同平台上编译(或交叉编译)和运行的意义。到目前为止:linux、windows、android(本机,通过没有 GUI 的终端仿真器)和 OpenBSD(strcat/strcpy 只需要替换为 strlcat/strlcpy 2 行)。 我担心如果我在 linux x86_64、android arm-something、windows 32 之间使用相同的二进制数据文件,存储的 float/double 会发生什么某事,等等...我希望有一种方法可以在二进制文件中强制执行浮点值的唯一大小和表示。
大多数浮点是 IEEE 754、64 位或 32 位。然而,如果你的处理器中的浮点单元不兼容,就没有现实有效的方法让它兼容,因此当 运行 在不同的机器上时,程序会产生略微不同的结果。 (这实际上是对声音程序的一个很好的测试 - 如果由于浮点错误导致结果显着不同,那么你处理的浮点运算很糟糕)。
但是,您可以在二进制文件中以可移植的方式加载和保存最接近 IEEE 754 的表示形式。代码在这里维护 here
对于货币,建议进行特殊处理。 Select 一种固定宽度的整数类型,以满足范围需求(int64_t
或 int32_t
)并按最小货币单位缩放。如果代码只有 storing/reading 个值,例如 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;
}