C:将双精度转换为单精度,保留小数点精度

23

我想在C语言中将double类型转换为float类型,但是想尽可能精确地保留小数点,而不做任何改动...

举个例子,假设我有以下数字:

   double d = 0.1108;
   double dd = 639728.170000;
   double ddd = 345.2345678

请纠正我,如果我说错了的话,我知道浮点数精度在小数点后面大约是5个数字。我能够完全获取双精度浮点数小数点后的那五个数字吗?这样以上结果将如下:

   float f = x(d);
   float ff = x(dd);
   float fff = x(ddd);

   printf("%f\n%f\n%f\n", f, ff, fff);

它应该打印

   0.1108
   639728.17000
   345.23456

我假设精度限制为5,那么在此之后的所有数字都会被截断。


10
浮点精度更准确地说应该是“有效数字位数”,而不是“小数点后的数字位数”。对于一个浮点数,12345678.12345很可能无法被表示得特别精确。 - Will A
11
除了已经评论和回答的关于浮点数表示的误解之外,你要找的函数 x 是从 doublefloat 的强制类型转换 (float)。如果您没有更改默认的最近偶数舍入模式,这个转换计算出最接近所转换的 doublefloat。没有比这更好的转换方式了,因此如果这种方法对于您的要求失去了太多的精度,请保留原始的 double - Pascal Cuoq
2
截断并不是将它们转换为数字的最准确方式——345.2345678更接近于345.23457而不是345.23456。 - caf
你想要的是不可能的。float没有那么多的精度(假设它是IEEE单精度)。为什么要使用float而不是double - R.. GitHub STOP HELPING ICE
3个回答

39

floatdouble不存储小数位,它们存储二进制位: float(假设IEEE 754)有24个有效位(7.22个十进制数字),而double有53个有效位(15.95个有效数字)。

double转换为float会给你最接近的可能的float,所以四舍五入对你没有帮助。反过来进行转换可能会在十进制表示中产生“噪点”数字。

#include <stdio.h>

int main(void) {
    double orig = 12345.67;
    float f = (float) orig;
    printf("%.17g\n", f); // prints 12345.669921875
    return 0;
}

要得到一个接近你想要的好看小数值的double近似值,你可以像这样编写代码:

double round_to_decimal(float f) {
    return round(f * pow(10, 7)) / pow(10, 7);
}

@davidvandebunte:那只是在C++中。问题标记为C。 - dan04
6
round_to_decimal函数中逐个遍历字符串似乎是个糟糕的想法。肯定有更好的数学方法可以实现这个功能。 - csl

13

float通常精确到小数点后7位数字,不受小数点位置影响。因此,如果需要小数点后5位的精度,则需要将数字范围限制在大约+/-100以内。


-3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接