0

I am writing an application wherein I have to log the received data with timestamp in milliseconds. This is my code

struct timespec ts;
struct tm tt;

clock_gettime(CLOCK_REALTIME,&ts);
localtime_r(&ts.tv_sec,&tt);

double d=(tt.tm_hour*3600+tt.tm_min*60+tt.tm_sec)*1000.0+ts.tv_nsec/1000000.0;
float f1=(tt.tm_hour*3600+tt.tm_min*60+tt.tm_sec)*1000.0f+ts.tv_nsec/1000000.0f;
float f2=(tt.tm_hour*3600+tt.tm_min*60+tt.tm_sec)*1000.0f;
float f3=ts.tv_nsec/1000000.0f;
float f4=f2+f3;

printf("d=%lf\tf1=%f\tf2=%f\tf3=%f\tf4=%f\n",d,f1,f2,f3,f4);

This is a sample output that got printed,

d=84137605.580233 f1=84137608.000000 f2=84137000.000000 f3=605.580200 f4=84137608.000000

But here the outputs of double variable d and float variables f1 & f4 are different. Can somebody tell me the reason for this.

Harry
  • 2,177
  • 1
  • 19
  • 33
  • That sounds like a standard loss-of-precision issue due to `float`s and `double`s not being able to precisely represent all real numbers. – templatetypedef Oct 23 '17 at 18:06
  • 1
    Pretty simple answer, floats have only 7-8 decimal digits accuracy. You are way beyond this. And using floating point logic here isn't quite recommended, instead consider using a fixed-point represntaition. – Constantine Georgiou Oct 23 '17 at 18:07
  • @ConstantineGeorgiou Seconded. Also, [never add floating point values.](http://www.volkerschatz.com/science/float.html) – Cloud Oct 23 '17 at 18:14
  • Alternative for the higher level goal: Accumulate the time as an integer in ms and print time as a `double`. `long long t_ms = ((tt.tm_hour*60LL+tt.tm_min)*60+tt.tm_sec)*1000+ts.tv_nsec/1000000; ... printf("t %0.3f\n",t_ms/1000.0);` – chux - Reinstate Monica Oct 23 '17 at 18:44

1 Answers1

1

Note that 84137605 is 0x503D685 in hex, so 27 bits are needed to represent it with full precision. An IEEE float has 24 bits of precision (23 fraction bits plus one hidden bit). So, you lose.

Doug Currie
  • 40,708
  • 1
  • 95
  • 119