【问题标题】:Why is this floating point addition result not correct?为什么这个浮点加法结果不正确?
【发布时间】:2015-06-09 15:14:46
【问题描述】:

我正在尝试以微秒为单位计算 buffer 中的时间。

但是我不明白为什么我的代码的浮点运算结果不正确。

float time, sec; 
int h, m;
sscanf(16:41:48.757996, "%d:%d:%f", &h, &m, &sec);
printf("buffer %s\n",buffer);
printf("hour %d\n",h);
printf("minute %d\n",m);
printf("seconde %f\n",sec);
time=3600*h+60*m;+sec;
printf("%f\n",time);

当我执行这段代码时,我得到以下结果:

buffer 16:41:48.757996
heure 16
minute 41
seconde 48.757996
60108.757812

但我期待:

buffer 16:41:48.757996
heure 16
minute 41
seconde 48.757996
60108.757996

浮点运算的结果不正确。

【问题讨论】:

  • 浮点算术有很多陷阱,甚至连长时间的程序员也会感到惊讶。只需谷歌即可,
  • @olaf 谢谢你,但是怎么办呢?我没有想法!请帮帮我!
  • 这里有一个提示:查看类型的名称:floating-point。除非您希望该点能够“浮动”,即由于操作而更改其任一侧的位数,否则您不需要使用这种类型。它不是,也不应与通用小数类型混淆(您始终可以使用缩放整数运算)。

标签: c floating-point printf addition


【解决方案1】:

我认为,您的代码中有一个小错字。改变

time=3600*h+60*m;+sec;

time=3600*h+60*m+sec;  // remove ; from the apparent middle of the statement
                ^^

否则,sec 值将变得基本上无用。

也就是说,始终检查sscanf() 的返回值以确保成功。


编辑:

正如其他人指出的那样,丢失精度的主要原因是由于使用了float 类型。 this answer 中很好地解释了,将变量类型更改为 double 将提高精度,并且您将获得细粒度的结果,正如您所期望的那样。

【讨论】:

  • 当我显示它时,秒值是正确的。但是计算的值不正确...我想以微秒为单位显示时间值,但它不正确。
  • 是的但是我不明白为什么你说检查sscanf()的返回值而h、m和sec的值是好的。问题只是关于计算
  • @flat1991 好吧,这只是一个建议,(这就是为什么最后出现的原因)。更像是“良好的编码习惯”的象征。
  • 这没有回答问题。
  • @hacks 你是对的。我的错。我一指出那个错字就停止关注。我应该注意到,错误应该会导致更大的价值差异。将更新我的答案,谢谢。 :-)
【解决方案2】:

根据IEEE 754 编码,许多数字会有微小的变化以允许它们被存储。此外,有效数字的数量可能会略有变化,因为它是二进制表示,而不是十进制表示。

单精度(浮点型) 为您提供 23 位 有效位、8 位指数和 1 位符号位。

双精度 (double) 为您提供 52 位 有效位、11 位指数和 1 位符号位。

以下代码 sn-p 将为您工作

#include<stdio.h>
#include <stdlib.h>

int main()
{
    double time, sec; // changed to double
    double h, m;
    sscanf("16:41:48.757996", "%lf:%lf:%lf", &h, &m, &sec);
    printf("hour %lf\n",h);
    printf("minute %lf\n",m);
    printf("seconde %lf\n",sec);
    time=3600*h+60*m+sec;
    printf("%lf\n",time);
}

【讨论】:

  • 通常可以将隐藏位添加到有效位数的位中,从而给出一个单精度数的有效位数为 24 位,同样,双精度数的有效位数为 53 位。
【解决方案3】:

如果想要更精确,请将 float 更改为 double

double time, sec;   

并在sscanf 中使用%lf。你会得到想要的结果。

Live Demo

【讨论】:

  • 谢谢。最后两行:time=3600*h+60*m;+sec; printf("%f\n",time);可以这样吗?
  • 是的。除非您需要从 time=3600*h+60*m;+sec; 中删除 ;
  • 这与精度无关。 float 可以满足他的目的。是错字弄乱了结果。
  • @mastov;什么?你是认真的吗?
  • @hacks: 好的,由于float,也有一些精度损失,但拼写错误的影响要大得多。
【解决方案4】:

用双打计算很好!

double time, sec;
sscanf(buffer, "%d:%d:%lf", &h, &m, &sec);
printf("buffer %s\n",buffer);
printf("heure %d\n",h);
printf("minute %d\n",m);
printf("seconde %f\n",sec);

P.TempsEmission=3600*h+60*m+sec;    
printf("%lf\n",P.TempsEmission);

【讨论】:

    猜你喜欢
    • 2016-05-02
    • 1970-01-01
    • 1970-01-01
    • 2020-07-13
    • 2019-07-08
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    相关资源
    最近更新 更多