В C есть разница между целым делением a/b и floor (a/b), где оба a и b являются целыми числами? Более конкретно, что происходит во время обоих процессов?C целочисленное деление и пол
ответ
a/b
делает целое подразделение. Если либо a
, либо b
отрицательный, результат зависит от компилятора (округление может идти к нулю или к отрицательной бесконечности в пред-C99, а в C99 + округление идет к 0). Результат имеет тип int
. floor(a/b)
выполняет одно и то же деление, преобразует результат в double, отбрасывает (несуществующую) дробную часть и возвращает результат как двойной.
floor
возвращает double
в то время, когда оба a/b
a
и b
являются целыми числами дает целое значение.
С правильным листом значение будет одинаковым.
Если typeof
оператор существует в С (это не делает) мы имеем:
(typeof (a /b)) floor(a/b) == a/b
EDIT: Теперь, если вопрос: есть ли разница между:
(double) (a/b)
и
floor(a/(double) b)
Ответ на этот вопрос да. Результаты отличаются относительно отрицательных значений.
Возможно потерять преобразование информации из целого числа в плавающую точку. Не вероятно, с междунар и дважды, но с небольшим изменением:
#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
Двойной может точно хранить все 32-битные целочисленные значения. Вы всегда можете использовать double вместо int. Это вряд ли потеряет точность, ее невозможно. Ваш пример верен, но вводит в заблуждение людей, которые еще не понимают проблему. – maxy
В общем, если предположить, что целые числа представимы как в целое число и типы с плавающей точкой, там ISN Разница, но доказательство не очевидно. Проблема в том, что в точке с плавающей точкой округление происходит в делении a/b, так что функция пола не применяется к точному рациональному значению, а к приблизительному значению. Я написал статью на эту тему: https://www.vinc17.net/research/publi.html#Lef2005b
Короче говоря, результат, который я получил, состоит в том, что если a -b точно представляется в системе с плавающей запятой, то floor (a/b), где a и b - числа с плавающей запятой (с целыми значениями), дает тот же результат, что и целочисленное деление a/b.
В C целочисленное деление выполняет усечение в направлении нуля. Это верно с C99 до того, как оно было определено реализацией. – ouah
А, пропустил тег 'C'. Тем не менее, ясно, что мой ответ о C++. '' –
@ Мистическое значение состоит в том, что 'floor' не округляет ничего в этом экземпляре, потому что' a/b' выполняет целочисленное деление и * затем * передает его на 'floor'. – oldrinb