说单精度碰撞的第一个数字是 131072.02 是否正确?(阳性,将 2 位数字视为尾数)
Is it correct to state that the first number that collide in single precision is 131072.02? (positive, considering 2 digits as mantissa)
我试图为我的音频应用程序弄清楚它是否可以用于正确表示我将使用的参数范围float
。
它需要的"最大"掩码是频率参数,这是正数,并且允许最多两位数作为尾数(即从 20.00Hz 至 22000。00赫兹)。从概念上讲,以下数字将被四舍五入,所以我不在乎它们。
所以我做了这个脚本来检查第一个以单精度碰撞的数字:
float temp = 0.0;
double valueDouble = 0.0;
double increment = 1e-2;
bool found = false;
while(!found) {
double oldValue = valueDouble;
valueDouble += increment;
float value = valueDouble;
// found
if(temp == value) {
std::cout << "collision found: " << valueDouble << std::endl;
std::cout << " collide with: " << oldValue << std::endl;
std::cout << "float stored as: " << value << std::endl;
found = true;
}
temp = value;
}
它似乎131072.02
(带有131072.01
,存储为相同的131072.015625
值),远于22000.00。看来我可以使用浮点数。
但我想了解这种推理是否正确。是的?
整个问题是,如果我设置一个 XXXXX.YY (7 digits
) 的参数,并且它与其他一些位数较少的数字发生冲突(因为single precision
只能保证6 digits
)
注意:当然,诸如1024.0002998145910169114358723163604736328125
或1024.000199814591042013489641249179840087890625
之类的数字会碰撞,并且它们在间隔内,但它们的表示数字比我要求的尾数更长,所以我不在乎。
IEEE 754 单精度定义为
- 1 个符号位
- 8 个指数位:范围 2^-126 到 2^127 ~ 10^-38 到 10^38)
- 23 分数(尾数)位:十进制精度取决于指数)
在 22k 处,指数将表示 16384=2^14 的偏移量,因此 23 位尾数将为您提供 2^14/2^23= 1/2^9 = 0.001953125 的精度......这对您的情况来说已经足够了。
对于 131072.01,指数将表示偏移量 131072 = 2^17,因此尾数将给出 2^17/2^23 = 1/2^6 = 0.015625 的精度,这比您的目标精度 0.01 大
你的程序没有准确地验证你想要什么,但你的基本推理应该是可以的。
该程序的问题在于 valueDouble 会累积轻微的错误(因为 0.01 不能准确表示) - 将字符串"20.01"转换为浮点数将引入轻微的舍入误差。
但是这些错误应该在DBL_EPSILON量级上,并且比您看到的错误小得多。
如果你真的想测试它,你必须写"20.00"到"22000.00",并使用你计划使用的scanf变体扫描它们,并验证它们是否不同。
单精度碰撞的第一个数字是 131072.02 是否正确?(正数,考虑小数点后 2 位数字
作为尾数)
是的。
我想了解这个推理是否正确。是的?
对于仅小于 131072.0f 的值,每个连续的可表示float
值相距 1/128。
对于 [131072.0f ...2*131072.0f),每个连续的可表示float
值相距 1/64。
对于十进制文本形式"131072.xx"的值,有 100 种组合,但只有 64 种不同float
。 发生 100-64 或 36 次碰撞并不奇怪 - 见下文。 对于这种形式的数字,这是float
密度太稀疏的第一个地方:在这个范围内float
> 0.01 中的最小有效位。
int main(void) {
volatile float previous = 0.0;
for (long i = 1; i <= 99999999; i++) {
volatile float f1 = i / 100.0;
if (previous == f1) {
volatile float f0 = nextafterf(f1, 0);
volatile float f2 = nextafterf(f1, f1 * 2);
printf("%f %f %f delta fraction:%fn", f0, f1, f2, 1.0 / (f1 - f0));
static int count = 100 - 64;
if (--count == 0) return 0;
}
previous = f1;
}
printf("Donen");
}
输出
131072.000000 131072.015625 131072.031250 delta fraction:64.000000
131072.031250 131072.046875 131072.062500 delta fraction:64.000000
131072.046875 131072.062500 131072.078125 delta fraction:64.000000
...
131072.921875 131072.937500 131072.953125 delta fraction:64.000000
131072.937500 131072.953125 131072.968750 delta fraction:64.000000
131072.968750 131072.984375 131073.000000 delta fraction:64.000000
为什么浮点数的有效数字是 7 或 6 也可能有所帮助。
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 检查输入是否不是整数或数字
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 如何用数字处理log(0)
- 最高有效数字侧的第N位
- 如何获取一个数字的前3位
- 查找最接近的大于当前数字的数字的索引
- 找到两对数字,使它们的乘积的绝对差最小化
- 我想做一个彼此不同但重复出现的数字
- 将数字转换为字母(例如:123 转换为一二三)
- C++如何计算用户输入的数字中的偶数位数
- 如何在C++中确定文本文件中的元素是字符还是数字
- 打印数字图案
- C++问题:用户认为数字1-100,程序提出问题不超过6次即可得到答案。无法正确
- 如何检查一个c++字符串中有多少相同的字符/数字
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 将数字打印成文字
- 当使用比格式支持的精度更高的精度来显示数字时,会写出什么数据
- 说单精度碰撞的第一个数字是 131072.02 是否正确?(阳性,将 2 位数字视为尾数)