В C есть разница между целым делением a/b и floor (a/b), где оба a и b являются целыми числами? Более конкретно, что происходит во время обоих процессов?
C целочисленное деление и пол
Ответ 1
a/b
выполняет целочисленное деление. Если значение a
или b
отрицательное, результат зависит от компилятора (округление может идти к нулю или к отрицательной бесконечности в pre-C99, а в C99 + округление идет к 0). Результат имеет тип int
. floor(a/b)
выполняет одно и то же деление, преобразует результат в double, отбрасывает (несуществующую) дробную часть и возвращает результат как двойной.
Ответ 2
floor
возвращает a double
, а a / b
, где оба a
и b
являются целыми числами, дают целочисленное значение.
При правильном нажатии значение будет одинаковым.
Если бы оператор typeof
существовал в C (это не так), мы бы имели:
(typeof (a /b)) floor(a / b) == a / b
EDIT: Теперь, если вопрос: есть ли разница между:
(double) (a / b)
и
floor(a / (double) b)
Ответ - да. Результаты отличаются относительно отрицательных значений.
Ответ 3
Возможно потерять преобразование информации из целого числа в плавающую точку. Неверно с int и double, но с небольшим изменением:
#include <stdio.h>
#include <math.h>
int main(void)
{
unsigned long long a = 9000000000000000003;
unsigned long long b = 3;
printf("a/b = %llu\n", a/b);
printf("floor(a/b) = %f\n", floor(a/b));
return 0;
}
Результат:
a/b = 3000000000000000001
floor(a/b) = 3000000000000000000.000000
Ответ 4
В общем случае, считая, что целые числа представляются как в целых, так и в типах с плавающей точкой, нет никакой разницы, но доказательство не является очевидным. Проблема в том, что в точке с плавающей точкой округление происходит в делении a/b, так что функция пола не применяется к точному рациональному значению, а к приблизительному значению. Я написал статью на эту тему: https://www.vinc17.net/research/publi.html#Lef2005b
Короче говоря, результат, который я получил, состоит в том, что если a -b точно представляется в системе с плавающей запятой, то floor (a/b), где a и b - числа с плавающей запятой (с целыми значениями), дает тот же результат, что и целочисленное деление a/b.