2009-05-17 2 views
2

Что такое хороший алгоритм для определения необходимой фракции, необходимой для добавления/суба к числу, чтобы округлить его до ближайшего целого, не используя встроенные потолочные или напольные функции?Дробная часть номера вопроса

Редактировать: Ищет математическое число трюк, чтобы выяснить часть, необходимую для округления числа до ближайшего целого. Чем более примитивны математические операции, тем лучше. Пожалуйста, избегайте использования других процедур. 0,5 можно взять в любом случае, независимо от того, что подходит вашему методу. Это НЕ мой вопрос о домашнем задании, и я не буду использовать его нигде.

+0

Можете ли вы использовать другие функции из стандартного api? Или вы действительно хотите реализовать свой собственный алгоритм, хотя это означает повторное использование колеса? –

+0

Вам разрешено бросать в int? Или это считается встроенной функцией пола? – DeadHead

+0

Извините, нет отливок. – unj2

ответ

4

Mod номер с одной, чтобы получить дробную часть, если его> 0,5, округлить вверх, еще округлить

ИЛИ

Разделите число на 0,5, если его нечетным, сгонять, еще раунд вниз

+1

Обратите внимание, что некоторые языки определяют только mod /% для целых чисел. – Stephan202

+0

Алгоритм умный , если х% 1> = 0,5 печать ((х- х% 1) + 1) -x еще печать х% 1 конец Можете ли вы думать о anothersolution без%? – unj2

+0

Любые другие ограничения? разделит ли трюк? – Simonw

3

Если вы не можете использовать мод (так как он может быть определен только для целых чисел в вашем языке, вы можете быть в состоянии сделать что-то вроде этого (в C-иш псевдокод):

// make the input positive: 
boolean inputPositive = true; 
if (input < 0) { 
    input = 0 - input; 
    inputPositive = false; 
} 

// subtract 1 until you just have the decimal portion: 
int integerPart = 0; 
while (input > 1) { 
    input = input - 1; 
    integerPart++; 
} 

int ret; 
if (input >= 0.5) { // round up 
    ret = integerPart + 1; 
} else { 
    ret = integerPart; 
} 

if (inputPositive) { 
    return ret; 
} else { 
    return 0 - ret; 
} 

Это решение не использует mod или любые внешние функции. Конечно, я не могу представить, почему вы хотели бы этого в реальной жизни. Интересно об этом подумать.

+1

Очень хороший ответ, согласно мне, он соответствует всем требованиям! :-) –

+0

+1, конечно, я забыл упомянуть .. ;-) –

+1

+1. Вы можете улучшить это, вычитая все меньшие полномочия в два, чтобы эта процедура также прекратилась в разумные сроки для больших входных данных. – Stephan202

3

Как только у вас есть дробная часть номера, проблема в значительной степени решена. Один из способов получить дробную часть состоит в том, чтобы многократно вычитать из вас число из двух (при условии, что оно было положительным, если было отрицательным для начала).

Функция, указанная ниже, getWholeMaker, возвращает то, что вы хотите («вещь», которую нужно добавить, чтобы округлить число). Это время работы O(log(n)) и использует только элементарные операции.

/* Returns the factional part of x */ 
double getFrac(double x) { 
    if(x < 0) x = -x; 
    if(x < 1) return x; 
    else if(x < 2) return x-1; 

    /* x >= 0 */ 
    double t = 2; 
    while(t+t <= x) t += t; 
    /* t is now the largest power of 2 less than or equal to x */ 
    while(t >= 1) { 
     if(t <= x) x -= t; 
     t /= 2; 
    } 

    return x; 
} 

double getWholeMaker(double x) { 
    double frac = getFrac(x); 
    double sign = x >= 0 ? +1 : -1; 
    return sign * (frac <= 0.5 ? -frac : 1-frac); 
} 
+0

Сладкий. Но это похоже на оптимизацию алгоритма pkaeding. Я прав? – unj2

+0

Да, это как pkaeding's, но работает в логарифмическом времени (pkaeding - это линейное время). –

Смежные вопросы