浮点数据类型不确定

Float data type uncertainty

我正在对我开发的数学软件进行数值分析。我想确定我的结果的不确定性是什么。作为 f() 我的方法和 x 输入值,我想将结果的 y 标识为 f(x) +/- y。我的 f() 方法在 float 变量之间有多个操作。要研究 f() 中发生的误差传播,我必须应用 不确定性统计传播 公式,为此我必须知道 [=18] 的不确定性=]变量。

我确实了解 IEEE 754 标准中指定的 float 变量的体系结构以及将十进制值转换为后者固有的 float 的舍入误差。

根据我对文献的了解,http://www.cplusplus.com/reference/cfloat/ 中的 FLT_EPSILON 宏 定义了我的 y 值,但这个快速测试证明它是错误的:

float f1 = 1.234567f;
float f2 = 1.234567f + 1.192092896e-7f;
float f3 = 1.234567f + 1.192092895e-7f;

printf("Inicial:\t%f\n", f1);
printf("Inicial:\t%f\n", f2);
printf("Inicial:\t%f\n\n", f3);

输出:

Inicial:  1.234567
Inicial:  1.234567
Inicial:  1.234567

当预期输出应该是:

Inicial:  1.234567
Inicial:  1.234568 <---
Inicial:  1.234567

我哪里错了? x + FLT_EPSILONx - FLT_EPSILONfloat值不应该一样吗?

编辑:我的问题是 R xfloat 值,x + y || x - y 等于相同 R float 值?

float f1 = 1.234567f;
float f2 = f1 + 1.192092897e-7f;
float f3 = f1 + 1.192092896e-7f;

printf("Inicial:\t%.20f\n", f1);
printf("Inicial:\t%.20f\n", f2);
printf("Inicial:\t%.20f\n\n", f3);

输出:

Inicial:        1.23456704616546630000
Inicial:        1.23456716537475590000
Inicial:        1.23456716537475590000

没有,你的期望是错误的
在第一个 printf 调用中,您打印的变量 f1 没有任何效果,它只是 1.234567f.

Float 是一个 32 位 IEEE 754 单精度浮点数:1 位用于符号,8 位用于指数,23* 用于值,即 float 具有 7 精度的十进制数字。

增加 printf 打印数字的数量以查看更多,但在 7 数字之后它只是噪音:

#include <stdio.h>

int main(void) {

 float f1 = 1.234567f;
 float f2 = 1.234567f + 1.192092897e-7f;
 float f3 = 1.234567f + 1.192092896e-7f;

 printf("Inicial:\t%.16f\n", f1);
 printf("Inicial:\t%.16f\n", f2);
 printf("Inicial:\t%.16f\n\n", f3);

 return 0;
}

输出:

Inicial:        1.2345670461654663                                                                                                           
Inicial:        1.2345671653747559                                                                                                           
Inicial:        1.2345671653747559 

Propagation of uncertainty is from the field of statistics and refers to how uncertainties in inputs affect mathematical functions of them. The analysis of errors that occur in computational arithmetic is numerical analysis.

FLT_EPSILON 不是 floating-point 结果中不确定性或误差的度量。它是 1 和 float 类型中可表示的下一个值之间的距离。因此,它是 1 级可表示数字之间的步长。

当您将十进制数字转换为 floating-point 时,所产生的舍入误差幅度可能高达 1/2 步长(如果使用普通 round-to-nearest 模式)。边界是 ½ 步长的原因是对于任何数字 x(在 floating-point 格式的有限域内),在 ½ 步长内有一个可表示的值(包括的)。这是因为,如果一个方向上的可表示数大于步长的 1/2,则另一个方向上的可表示数小于步长的 1/2。

步长随着数字的大小而变化。对于二进制 floating-point,它在 2 时加倍,然后在 4 时再次加倍,然后是 8,依此类推。低于 1,它减半,然后在 ½、¼ 等处再次减半。

当您执行 floating-point 算术运算时,计算中发生的舍入可能会合并或抵消以前的错误。最终误差没有通用公式。

示例代码中使用的两个数字 1.192092897e-7f1.192092896e-7f 靠得太近,以至于它们转换为相同的 float 值 2 −23。这就是为什么 f2f3.

没有区别的原因

f1f2是有区别的,但是你没有打印足够的数字来显示它。

你问“x + FLT_EPSILONx - FLT_EPSILONfloat值不应该一样吗?”,但你的代码不包含x - FLT_EPSILON.

回复:“我的问题是 R x 的浮点值,x + yy 值是多少 || x - y 等于相同的 R 浮点值?” y = 0 可以满足。你的意思是问满足条件的 y 的最大值是多少?有点复杂。

一个数字x的步长称为x的ULP,我们可以将其视为一个函数ULP(x)。 ULP 代表最小精度单位。它是x的floating-point表示中最小位的位值。它不是常数;它是 x.

的函数

对于大多数以 floating-point 格式表示的值,满足您条件的最大 y 是最小数字的 ½ ULP(x) x 的 floating-point 表示是偶数,如果数字是奇数,则刚好低于 ½ ULP(x)。这种复杂性源于以下规则:算术结果四舍五入到最接近的可表示值,如果出现平局,则选择偶数位较低的值。因此,将 ½ ULP(x) 添加到 x 将产生平局,如果低位是偶数,但如果低位是奇数,则不会四舍五入到 x

但是,对于x,在ULP变化的边界上,满足你条件的最大y是¼ ULP(x )。这是因为,就在x(量级)下方,步长发生变化,下一个低于x的数字是[=59的一半=]x 的步长而不是通常的全步长。所以你只能在改变减法结果之前向那个值走一半,所以最多 y 可以是 ¼ ULP(x).