1

I tried to solve a task on codewars and happened something strange, in one case casting worked as usual and in the second o got strange behavior. Here is the code:

#include <stdio.h>
#include <string.h>
#include <math.h>
int digital_root(int n) {
  char tmp[30];
  char *ptr;
  while(n > 9){
    sprintf(tmp, "%d", n);
    int len = strlen(tmp);
    float n_tmp = n / (pow(10, len));
    n = 0;

    for(int i = 1; i <=len; i++){
      float t = n_tmp * (pow(10, i));
      printf(" vars = [%f , %d] ", t, (int)t); //this line
      n += (int) t;
      n_tmp -= (int)t/pow(10,i);

    }

  }

  return n;
}

int main()
{
    digital_root(16);

    return 0;
}

And the line printf(" vars = [%f , %d] ", t, (int)t); outputs: vars = [1.600000 , 1] vars = [6.000000 , 5], what is so strange. Can someone explain this behavior?

Stas Mercer
  • 89
  • 1
  • 10

1 Answers1

1

Every casting float to int is a rounding, so every time you do it, stop for a second and think: what kind of rounding do I need this time? Dropping the fractional part? floor()? ceil()? Or rounding positive float towards nearest int? If 5.999999999999 should be 6, use (int)(t+.5), not (int)t.

Or you can mimic the printf behavior and round only the smallest float fraction, which can vary (depending on the biggest value you use). (int)(t+.000001) will round both 1.9 to 1 (as it probably should), and 3.9999999999 to 4 (because it is 4 with some tiny number representation errors).

You should however know the size of a fraction which can be an actual, meaningful part of your data. Everything smaller than this fraction must be rounded. It can be either .00000001 or .5, that depends on your needs and the algorithm itself.

NickDoom
  • 339
  • 1
  • 9
  • 1
    *Every casting float to int is a rounding* No, it is not a "rounding", [it is a truncation](https://port70.net/~nsz/c/c11/n1570.html#6.3.1.4p1): "When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined." – Andrew Henle Feb 19 '20 at 22:13
  • Correct but AFAIK truncation is the kind of rounding (Wikipedia calls it "rounding towards zero, or truncation"). So "it's always a rounding and it'll be a truncation by default, unless you take special measures to use different rounding method". – NickDoom Feb 19 '20 at 22:23