C целочисленное деление и пол

В C есть разница между целым делением a/b и floor (a/b), где оба a и b являются целыми числами? Более конкретно, что происходит во время обоих процессов?

Ответ 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.