2012-09-02 6 views

ответ

11

a/b делает целое подразделение. Если либо a, либо b отрицательный, результат зависит от компилятора (округление может идти к нулю или к отрицательной бесконечности в пред-C99, а в C99 + округление идет к 0). Результат имеет тип int. floor(a/b) выполняет одно и то же деление, преобразует результат в double, отбрасывает (несуществующую) дробную часть и возвращает результат как двойной.

+2

В C целочисленное деление выполняет усечение в направлении нуля. Это верно с C99 до того, как оно было определено реализацией. – ouah

+0

А, пропустил тег 'C'. Тем не менее, ясно, что мой ответ о C++. '' –

+0

@ Мистическое значение состоит в том, что 'floor' не округляет ничего в этом экземпляре, потому что' a/b' выполняет целочисленное деление и * затем * передает его на 'floor'. – oldrinb

6

floor возвращает double в то время, когда оба a/ba и b являются целыми числами дает целое значение.

С правильным листом значение будет одинаковым.

Если typeof оператор существует в С (это не делает) мы имеем:

(typeof (a /b)) floor(a/b) == a/b 

EDIT: Теперь, если вопрос: есть ли разница между:

(double) (a/b) 

и

floor(a/(double) b) 

Ответ на этот вопрос да. Результаты отличаются относительно отрицательных значений.

4

Возможно потерять преобразование информации из целого числа в плавающую точку. Не вероятно, с междунар и дважды, но с небольшим изменением:

#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 
+1

Двойной может точно хранить все 32-битные целочисленные значения. Вы всегда можете использовать double вместо int. Это вряд ли потеряет точность, ее невозможно. Ваш пример верен, но вводит в заблуждение людей, которые еще не понимают проблему. – maxy

1

В общем, если предположить, что целые числа представимы как в целое число и типы с плавающей точкой, там ISN Разница, но доказательство не очевидно. Проблема в том, что в точке с плавающей точкой округление происходит в делении a/b, так что функция пола не применяется к точному рациональному значению, а к приблизительному значению. Я написал статью на эту тему: https://www.vinc17.net/research/publi.html#Lef2005b

Короче говоря, результат, который я получил, состоит в том, что если a -b точно представляется в системе с плавающей запятой, то floor (a/b), где a и b - числа с плавающей запятой (с целыми значениями), дает тот же результат, что и целочисленное деление a/b.