Приведение float к int не работает должным образом в C - PullRequest
1 голос
/ 19 февраля 2020

Я попытался решить задачу по кодовым войнам, и случилось что-то странное, в одном случае приведение работало как обычно, а во втором - странное поведение. Вот код:

#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;
}

И строка printf(" vars = [%f , %d] ", t, (int)t); выводит: vars = [1.600000, 1] vars = [6.000000, 5] , что странно. Может кто-нибудь объяснить это поведение?

1 Ответ

1 голос
/ 20 февраля 2020

Каждое приведение к int - это округление, поэтому каждый раз, когда вы делаете это, останавливайтесь на секунду и думайте: какого округления мне нужно на этот раз ? Сбрасывает дробную часть? этаж()? CEIL ()? Или округление положительного числа в сторону ближайшего int? Если 5.999999999999 должно быть 6, используйте (int)(t+.5), а не (int)t.

Или вы можете имитировать поведение c printf и округлять только наименьшую дробь float, которая может варьируются (в зависимости от наибольшего значения, которое вы используете). (int)(t+.000001) округляет и 1.9 до 1 (как это, вероятно, следует), и от 3.9999999999 до 4 (поскольку равно 4 с некоторыми незначительными ошибками представления чисел).

Однако следует знать размер дроби, которая может быть реальной, значимой частью ваших данных. Все, что меньше этой дроби, должно быть округлено. Это может быть .00000001 или .5, в зависимости от ваших потребностей и самого алгоритма.

...