如何正确地规范化C ++中的浮点值?

时间:2013-12-09 15:59:51

标签: c++ floating-point double ieee-754

也许我不太了解IEEE754标准,但给出了一组floatdouble的浮点值,例如:

56.543f 3238.124124f 121.3f ...

您可以将其转换为01之间的值,因此您可以通过采用适当的公因子来对其进行标准化,同时考虑集合中的最大值和最小值

现在我的观点是,在这个转换中,如果与我在第一个中需要的精度水平相比,我需要更高的目标集合精度,范围从01 ,特别是如果第一组中的值涵盖了大范围的数值(非常大且非常小的值)。

floatdouble(或IEEE 754标准,如果需要)类型如何处理这种情况,同时为第二组值提供更高的精度,因为我知道我基本上不需要整数部分?

或者它根本不处理这个问题,我需要一个完全不同类型的定点数学?

5 个答案:

答案 0 :(得分:5)

浮点数以类似于科学记数法的格式存储。在内部,它们将二进制表示的前导1与有效数字的顶部对齐。每个值都使用相对于其自身大小的相同数量的精度二进制数字来承载。

当您将浮点值集合压缩到0..1范围时,您将获得的唯一精度损失将归因于该过程的各个步骤中发生的舍入。

如果你只是通过缩放进行压缩,你将在尾数的LSB附近失去很少的精度(大约1或2 ulp,其中ulp表示“最后位置的单位”)。

如果您还需要转移数据,那么事情会变得棘手。如果您的数据都是正数,则减去最小数字不会损坏任何数据。但是,如果您的数据是正数据和负数据的混合,那么接近零的某些值可能会降低精度。

如果以double精度执行所有算术运算,则通过计算将获得53位精度。如果你的精确度需要在那个范围内(他们可能会这样做),那么你会没事的。否则,确切的数值性能将取决于数据的分布。

答案 1 :(得分:3)

单和双IEEE浮点数具有指数和小数部分具有固定位宽的格式。所以这是不可能的(即如果你只存储0到1之间的值,你将总是有未使用的位)。 (见:http://en.wikipedia.org/wiki/Single-precision_floating-point_format

你确定双精度的52位宽部分不够精确吗?

编辑:如果使用浮动格式的整个范围,则在规范化值时将失去精度。舍入可以关闭,足够小的值将变为0.除非您知道这是一个问题,否则不要担心。否则你必须查找其他答案中提到的其他解决方案。

答案 2 :(得分:2)

为了获得更高的精确度,您可以尝试http://www.boost.org/doc/libs/1_55_0/libs/multiprecision/doc/html/boost_multiprecision/tut/floats.html

另请注意,对于数值关键运算+, - 有一些特殊算法可以最小化算法引入的数值误差:

http://en.wikipedia.org/wiki/Kahan_summation_algorithm

答案 3 :(得分:2)

如果您选择double并将其标准化为0.01.0之间,则会有许多精确丢失的来源。然而,它们都比你怀疑的要小得多。

首先,当发生舍入时,您将失去对其进行标准化所需的算术运算的一些精度。这相对较小 - 每次操作有点左右 - 通常相对随机。

其次,指数成分将不再使用正指数可能性。

第三,由于所有值均为正值,因此符号位也将被浪费。

第四,如果输入空间不包括+ inf或-inf或+ NaN或-NaN等,那么这些代码点也将被浪费。

但是,在大多数情况下,你会在规范化中浪费大约3位信息64位double,其中一种是当你处理有限时几乎不可避免的事情。位宽值。

从0到1的值的任何64位定点表示将比double具有更少的“范围”。 double可以表示大约10^-300的内容,而包含1.0的64位定点表示只能低至10^-19左右。 (64位定点表示可以表示1 - 10^-191不同,而double则不能,但64位定点值不能表示小于{{1}的任何值},而2^-64可以)。

上面的一些数字是近似值,可能取决于舍入/精确格式。

答案 4 :(得分:2)

具有二进制浮点值(带有隐式前导值),表示为

(1+fraction) * 2^exponent where fraction < 1

分部a / b是:

a/b = (1+fraction(a)) / (1+fraction(b)) * 2^(exponent(a) - exponent(b))

因此,除法/乘法基本上没有精度损失。

减法a-b是:

a-b = (1+fraction(a)) * 2^(exponent(a) - (1+fraction(b)) * exponent(b))

因此减法/加法可能会失去精确度(大 - 微= =大)!

将[min,max]范围内的值x钳制到[0,1]

(x - min) / (max - min)
如果任何减法都有精度损失,

会出现精度问题。

回答你的问题: 没什么,为您的算法和预期数据选择合适的表示(浮点,分数,多精度......)。