我正在编写一段代码,需要将双精度数转换为单精度数。我使用boost::numeric_cast来执行此转换,以便在溢出/下溢时发出警告。但是,我还想知道这个转换是否导致了精度损失。
例如
double source = 1988.1012;
float dest = numeric_cast<float>(source);
产生值为1988.1的dest。
是否有任何可用的方法可以检测这种精度丢失/四舍五入?
我正在编写一段代码,需要将双精度数转换为单精度数。我使用boost::numeric_cast来执行此转换,以便在溢出/下溢时发出警告。但是,我还想知道这个转换是否导致了精度损失。
例如
double source = 1988.1012;
float dest = numeric_cast<float>(source);
产生值为1988.1的dest。
是否有任何可用的方法可以检测这种精度丢失/四舍五入?
您可以将浮点数转换回double类型,并将其与原始值进行比较 - 这应该可以给您一个关于是否存在精度损失的公正指示。
float dest = numeric_cast<float>(source);
double residual = source - numeric_cast<double>(dest);
因此,residual
包含了你正在寻找的“损失”。查看这些有关单精度和双精度浮点数的文章。首先,浮点数的指数有8位,而双精度有11位。因此,任何大于10^127或小于10^-126的数量级都会像您提到的那样溢出。对于浮点数,您有23位用于数字的实际位数,而双精度则有52位。因此,显然,双精度比浮点数具有更多的精度位数。
假设你有一个数字,比如1.1123。这个数字可能实际上并没有被编码成1.1123,因为浮点数中的数字实际上是用来相加作为分数的。例如,如果你的尾数位是11001,那么这个值将由1(隐含)+ 1 * 1/2 + 1 * 1/4 + 0 * 1/8 + 0 * 1/16 + 1 * 1/32 + 0 *(64 + 128 + ...)组成。因此,除非你能以确切的方式相加这些分数得到精确的数字,否则无法编码精确的值。这是很少见的。因此,几乎总会存在精度损失。根据Dave的回答,您将会有一定程度的精度损失。然而,如果您想要关注量化并在超过某个数字时引发异常,您将需要打开浮点数本身并解析出尾数和指数,然后进行一些分析以确定是否超出了您的容差。
但好消息是,它通常是标准的IEEE浮点数!:-)