1

Given the following code (specifically using Embarcadero C++ Builder XE3):

int GetNDig(float fVal, float fTol) {
  int tolCoeff = floor(-1 * (logf(fTol)/logf(10)));
  int nDig = tolC - floor(logf(fVal)/logf(10));
  if (nDig < 0) {
    nDig = 0; // Limit to 0
  }
  return nDig;
}

void ButtonClick(...) {
  float val = 12.3456789;
  tol = 0.001;
  int nDig = GetNDig(val,tol);
  String sDig = (String)"%." + nDig + "f";
  Label1->Caption = Format("Output: " + sDig,ARRAYOFCONST((val)));
}

According to https://en.cppreference.com/w/c/numeric/math/log, logf(), log(), and logl() are essentially the same except for the size of the floating-point types they deal with (float, double, and double-double respectively).

In my GetNDig() function I expect that when I pass in fTol = 0.001 I will always calculate the variable tolCoeff = 3, 0.01 => 2, 0.1 => 1, etc., regardless of the flavor of logx() used. HOWEVER, my problem is this:

  • -1 * (log(0.001)/log(10)) => 2
  • -1 * (logf(0.001)/logf(10)) => 3
  • -1 * (logl(0.001)/logl(10)) => 2

Could this be a <math.h> library issue specific to C++ Builder XE3, or am I doing something wrong in my own code?

depwl9992
  • 150
  • 1
  • 13
  • `0.001` is not exactly representable as a binary floating-point number. Representational error in this number likely differs between floating-point formats. Transcendental functions like `log` typically have some small amount of error in the returned results. If you are lucky your compiler's documentation will provide upper bounds on that error. Considering these facts in combination, it is not realistic to assume that this computation provides the mathematical result. See also: https://stackoverflow.com/questions/588004/is-floating-point-math-broken – njuffa Oct 28 '20 at 00:23
  • use `round` instead of `floor` – M.M Oct 28 '20 at 00:57
  • @njuffa I've always wondered what caused this sort of thing. I'll re-examine and see if that's what's going on here. Thanks! – depwl9992 Oct 29 '20 at 17:13

0 Answers0