提问人:Charles 提问时间:10/25/2023 更新时间:10/26/2023 访问量:37
快速计算出 32 位浮点表示和相关损耗的方法
Quick way to figure out 32-bit floating point representation and associated loss
问:
我正在处理来自高精度系统的给定范围(即朗度和滞后度)的实数,这将为我提供许多小数(通常以 15 为量级,当然还有逗号最多剩三位)。现在,这些小数点在多大程度上代表了实际的知识,我不知道,但我想把它们都用起来。
问题是,对于任何给定的数字,如何快速知道 32 位浮点表示是否会在小数位上产生任何损失,如果是,损失多少?有没有一些在线工具可以做到这一点,或者我可以在 excel 表格或其他东西中进行一些快速计算?
答:
0赞
chux - Reinstate Monica
10/26/2023
#1
最坏情况下的二进制损失是关于 和 的精度差异。通常为 29 位。十进制损失约为 29 * log10(2) 或 8.7 十进制数字损失。float64
float32
对于特定值,有些值会完全转换为 .float32
float64
与其试图找到十进制损失,不如让我们看一下二进制损失,因为常见的 float32
和 float64
采用二进制浮点编码。
与这种角度的情况一样,范围不是什么大问题,请考虑提取 的有效位,并评估其与保留位相比的最低有效位。float64
#include <float.h>
#include <math.h>
#define DBL_FLT_DIG_DIFF (DBL_MANT_DIG - FLT_MANT_DIG)
#define DBL_FLT_DIG_DIFF_MOD (1ull << DBL_FLT_DIG_DIFF)
// Return loss in fraciton of a ULB of x as a float.
double double_to_float_loss(double x) {
if (x < 0) {
return double_to_float_loss(-x);
const double scale = DBL_FLT_DIG_DIFF_MOD;
// The frexp functions break a floating-point number into a normalized
// fraction and an integer exponent
int expo;
long long ifraction = (long long) (frexp(x, &expo) * scale);
long long loss = ifraction % DBL_FLT_DIG_DIFF_MOD;
ifraction /= DBL_FLT_DIG_DIFF_MOD;
// 0.5 as conversion from float64 to float32 typically rounds to nearest.
return 0.5 * loss/ifraction;
}
小数点后位置的损失,
对于给定的,很简单,只需从上面评估小数位数即可。float64
loss
...
long long loss = ifraction % DBL_FLT_DIG_DIFF_MOD;
int deimcal_loss = 0;
while (loss) {
loss /= 10;
decimal_loss++;
}
更糟糕的情况:log10(DBL_FLT_DIG_DIFF_MOD)
评论
num_decimals_representable = log10(2^(num_bits_for_mantissa)