【问题标题】:C: convert double to float, preserving decimal point precisionC:将double转换为float,保留小数点精度
【发布时间】:2011-03-30 17:13:07
【问题描述】:

我想在 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)之后的所有数字都将被截断。

【问题讨论】:

  • 浮点精度更准确地表述为“有效位数”而不是“小数位后的位数”。 12345678.12345 很可能无法通过浮点数特别准确地表示。
  • 除了对已评论和回答的浮点数表示的误解外,您正在寻找的函数x是从double转换为float(float)。如果您没有从默认的最接近偶数更改舍入模式,则此转换计算最接近您正在转换的doublefloat。没有比这个更好的转换了,所以如果这个对你的口味失去了太多的精度,请保持你的 doubles 不变。
  • 截断不是转换它们的最准确方法 - 345.2345678 比 345.23456 更接近 345.23457
  • 你想要的都是不可能的。 float 没有那么高的精度(假设它是 IEEE 单精度)。为什么要使用float 而不是double

标签: c floating-point double c89


【解决方案1】:

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) {
    char buf[42];
    sprintf(buf, "%.7g", f); // round to 7 decimal digits
    return atof(buf);
}

【讨论】:

  • @davidvandebunte:那只是在 C++ 中。该问题被标记为 C。
  • 遍历round_to_decimal 中的字符串似乎是一个可怕的想法。肯定有更好的方法来做一些数学运算。
【解决方案2】:

浮点数以科学计数法表示为只有七个有效数字的数字乘以代表小数位的较大数字。 有关它的更多信息,请访问 Wikipedia:

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

【讨论】:

    【解决方案3】:

    float 的精度一般在 7 位左右,与小数点位置无关。因此,如果您想要小数点后 5 位的精度,则需要将数字的范围限制在 +/-100 左右。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-29
      • 1970-01-01
      • 2019-06-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-02
      • 1970-01-01
      相关资源
      最近更新 更多