0

Assigning a double value, stored in variable A to a variable B alters it's value as soon the value gets below 0.000001. I've read about about problems with 80 Bit FPU's, but in this case, that problem shouldn't occur, as I'm only assigning a value, not calculating something with it. Here is some piece of example code:

double elapsed = _sinceCreation.elapsed();
if ( benchmark->minTime > elapsed ) {
   benchmark->minTime = elapsed;
}

benchmark->minTime should equal _sinceCreation.elapsed(), but it surprisingly doesn't! What could be the reason for this? And how can I fix this behavior?

EDIT:

To complete my explanation, here is the method where it behaves weird (inclusive testing output to verify equality):

double elapsed = _sinceCreation.elapsed();

if ( _benchmarkMap.find(benchmark->methodName) == _benchmarkMap.end() ) {
  _benchmarkMap[benchmark->methodName] = benchmark;
}

if ( benchmark->times.size() >= _benchmarkLimitPerMethod ||
     benchmark->times.size() >= benchmark->times.max_size() ) {
  benchmark->times.pop_front();
  benchmark->maxSizeReached = true;
}

benchmark->times.push_back( elapsed );

if ( benchmark->minTime > elapsed ) {
  std::cout << printToString("before min time: {0:0.15f} elapsed: {0:0.15f}", benchmark->minTime, elapsed) << std::endl;
  benchmark->minTime = elapsed;
  std::cout << printToString("after min time: {0:0.15f} elapsed: {0:0.15f}", benchmark->minTime, elapsed) << std::endl;
}

if ( benchmark->maxTime < elapsed )
  benchmark->maxTime = elapsed;

_sinceCreation is a timestamp class, returning double secs since last setCurrentTime() and printToString() is a own wrapper for fmtlib.

Migsi
  • 107
  • 2
  • 10
  • 1
    Please provide a [mcve] – Richard Critten Jul 19 '17 at 16:10
  • You didn't show how you determined that the values are not equal. – PaulMcKenzie Jul 19 '17 at 16:10
  • https://stackoverflow.com/questions/17333/what-is-the-most-effective-way-for-float-and-double-comparison – Retired Ninja Jul 19 '17 at 16:11
  • 1
    That's a whole lot of "pushing" and "popping" values to prove that the values are not equal. I would have expected a simple line right after the assignment like `if (benchmark->mintime == elapsed) { ok } else { what!!?? }` – PaulMcKenzie Jul 19 '17 at 16:26
  • @PaulMcKenzie The "pushing" and "popping" has nothing to do with the prove. I just pasted the whole method, in case you want to see that too! However, on both cout lines, both values are the same, while on the first one the value is != 0, in the second one the values are == 0 and there is nothing else playing around with this variables. There must be an explanation for this behavior? – Migsi Jul 19 '17 at 16:31

1 Answers1

0

It is all about precision. There is a limited precision also for double. If you go beyond that, the value is corrupted. Doesn't matter if you compute anything or not, the assigning of a value is still an operation, the value goes through the processor register, and because is too "large" is get truncated

  • So I should use a `long double` instead, to increase the precision? – Migsi Jul 19 '17 at 16:10
  • You could try, but be aware, there is always a limit – Constantin Iliescu Jul 19 '17 at 16:11
  • I would also add that some numbers which seem easy to represent in decimal are hard to in binary. For example, .1 seems easy to represent in decimal. It's the basic unit, while in binary you are working with .5, .25, .125 ... ad nauseam of bits. representing .1 is represented as 00111101110011001100110011001101 in IEEE format. This value is equivalent to 0.100000001490116119384765625, not .1 exactly. See: https://www.h-schmidt.net/FloatConverter/IEEE754.html – Erich Jul 19 '17 at 16:19
  • @Constantin Iliescu I tried it, it didn't help. Anyways, the operation of assignement shouldn't alter the precision at all, if the value gets assigned from 64bit to 64bit. – Migsi Jul 19 '17 at 16:21
  • The precision may be altered depending on the bit width of the hardware floating point support. Conversions from 64-bit to other bit sizes (larger or smaller) will affect precision. – Thomas Matthews Jul 19 '17 at 16:32