2010-04-04 2 views
0

Я кодирование до реализации Interpolation Search в С.Задание плавающего значения или использование функций math.h *?

вопрос на самом деле довольно просто, мне нужно использовать плавающие операции сделать линейную интерполяцию, чтобы найти правильный индекс, который в конечном счете будет целое результат.

В частности, индекс моего зонда:

t = i + floor((((k-low)/(high-low)) * (j-i))); 

, где, I, J, K, T являются беззнаковыми Интсами, и высоким, низким, удваивается.

Будет ли это эквивалентно:

t = i + (unsigned int)(((k-low)/(high-low)) * (j-i)); 

Есть ли какие-либо причине я бы на самом деле хочу использовать math.h пола * функцию над только простым (интермедиат) напечатанным?

ответ

1

Они эквивалентны только для положительных чисел. Из C99 спецификации (§6.3.1.4/1):

Когда значение конечного фи реальный фл типа с плавающим преобразуются в тип целого числа, кроме _Bool, дробная часть отбрасывается (то есть, значение усекается к нулю). Если значение , то целочисленная часть не может быть представлена ​​целым типом, поведение не определено.

Таким образом, для положительных чисел, результат литья значения с плавающей точкой к интегральному типу эквивалентен вызову floor, но отрицательное число эквивалентно вызову ceil.

+0

Понятно, спасибо за подробную информацию. Хорошая новость: ((k-low)/(high-low)) * (j-i) гарантированно будет> = 0, если алгоритм правильно закодирован (поскольку он является индексом в массив afterall). Так что это, по-видимому, подходящий вариант. Спасибо. – nobody

+1

@nobody: Обратите внимание, что с точки зрения производительности литье в интегральный тип может быть не быстрее, чем при использовании 'floor'. Кастинг для интегрального типа, вероятно, требует записи в память (на x86, все это почти гарантировано), при вызове 'floor' может и не быть, так как его результат является значением с плавающей запятой. Ваш пробег может отличаться, но следите за преждевременной и/или ошибочной оптимизацией. –

2

Они отличаются, когда значение < 0.

floor(-1.5) = -2.0 
(int)-1.5 = 1 
0

В вашем случае, они эквивалентны. Но для отрицательных чисел,

g++> printf("%g %d %u\n", floor(-5.5), (int)(-5.5), (unsigned)(-5.5)); 
-6 -5 0 

(на самом деле, бросая отрицательное вещественное число ≤ -1 до целого числа без знака зависит от реализации (или неопределенное поведение?).)

Кроме того, floor возвращает двойной, так i + floor(...) будет выполняться как операция с плавающей запятой, а не целочисленная операция.

+0

Отбрасывание отрицательного реального значения в неподписанный тип интеграла не определено: «Если значение интегральной части не может быть представлено целым типом, поведение не определено» (§6.3.1.4/1).Это несколько интересно, поскольку отличное отрицательное целочисленное значение для неподписанного интегрального типа _is_ четко определено: «если новый тип без знака, значение преобразуется путем многократного добавления или вычитания более чем максимального значения, которое может быть представлено в новый тип, пока значение не окажется в диапазоне нового типа »(§6.3.1.3/2). (цитаты из спецификации C99). –

+0

@James: Сноска (50) пишет * «Операция останова, выполняемая, когда значение целочисленного типа преобразуется в беззнаковый тип, не требуется выполнять, когда значение реального плавающего типа преобразуется в неподписанный тип». *, Который, как представляется, предполагает ожидаемое преобразование является «реальным -> подписанным -> неподписанным», не дает мне знать, должно ли оно быть неопределенным (как в 6.3.1.4) или определено в соответствии с реализацией (6.3.1.3). – kennytm