Доброго времени суток в блоге "Будни программиста".
Сегодня что-то стало скучно решил что-нибудь почитать. Взял в руки учебник по математике. :) Читал раздел про обыкновенные дроби, и десятичные дроби с бесконечной периодичностью.
Сразу же вспомнилась простая операция округления чисел в большую сторону. А именно, заинтересовал вопрос, есть ли какая-либо математическая формула для преобразования числа к необходимой точности? Единой формулы я, к сожалению, не нашел. Конечно я далеко не математик, но навскидку накидал алгоритм преобразования:
Даны 2 параметра:
Первый - число с плавающей точкой (назовем параметр - D).
Второй - параметр точности (назовем его - P).
Для примера возьмем число 0.557, и точность 2. Т.е. в итоге должно получиться 0.56.
Разложим решение задачи на этапы:
1) Умножение исходного числа D на 10 в степени P.
2) Из результата операции 1 (R) вычтем целую часть того же результата. Таким образом мы отделяем дробную часть от целой:
3) Главное действие округления.
Y = C + N,
где N - коэффициент преобразования.
N = 1 при 0.5 <= M <= 0.9;
N = 0 при 0 <= M< 0.5;
Y = 55 + 1 = 56;
4) Результат предыдущего преобразования делим на 10 в степени P:
Что соответствует ожидаемому результату.
Данный алгоритм, для проверки, я реализовал на C++:
double MyRound(double Value, int Precision)
{
if (Precision <= 0)
return (int)Value;
int PreQ;
PreQ = powl(10, Precision);
double Tmp = Value * PreQ;
int IntPart = (int)Tmp;
Tmp -=IntPart;
if ((Tmp>=0.5) && (Tmp<=0.9))
IntPart++;
return (double)IntPart/(double)PreQ;
}
Сегодня что-то стало скучно решил что-нибудь почитать. Взял в руки учебник по математике. :) Читал раздел про обыкновенные дроби, и десятичные дроби с бесконечной периодичностью.
Сразу же вспомнилась простая операция округления чисел в большую сторону. А именно, заинтересовал вопрос, есть ли какая-либо математическая формула для преобразования числа к необходимой точности? Единой формулы я, к сожалению, не нашел. Конечно я далеко не математик, но навскидку накидал алгоритм преобразования:
Даны 2 параметра:
Первый - число с плавающей точкой (назовем параметр - D).
Второй - параметр точности (назовем его - P).
Для примера возьмем число 0.557, и точность 2. Т.е. в итоге должно получиться 0.56.
Разложим решение задачи на этапы:
1) Умножение исходного числа D на 10 в степени P.
R = D * 10^P = 0.557 * 100 = 55.7
2) Из результата операции 1 (R) вычтем целую часть того же результата. Таким образом мы отделяем дробную часть от целой:
C = int(R) = int(55.7) = 55;
M = R - C = 55.7 - 55 = 0.7
3) Главное действие округления.
Y = C + N,
где N - коэффициент преобразования.
N = 1 при 0.5 <= M <= 0.9;
N = 0 при 0 <= M< 0.5;
Y = 55 + 1 = 56;
4) Результат предыдущего преобразования делим на 10 в степени P:
Result = Y/10^P = 56/100 = 0.56
Что соответствует ожидаемому результату.
Данный алгоритм, для проверки, я реализовал на C++:
double MyRound(double Value, int Precision)
{
if (Precision <= 0)
return (int)Value;
int PreQ;
PreQ = powl(10, Precision);
double Tmp = Value * PreQ;
int IntPart = (int)Tmp;
Tmp -=IntPart;
if ((Tmp>=0.5) && (Tmp<=0.9))
IntPart++;
return (double)IntPart/(double)PreQ;
}
Что-то математика начинает затягивать... :)
p.s. Алгоритм - просто развлекуха, в боевых условиях не проверял...
Если это этот код выполнять на сопроцессоре x87 результат может быть неверным как т.к. тип double расширяется в родной тип сопроцессора extented. Способ расширения задается в настройках сопроцессора, и может отличаться от предполагаемого, например 5.01 double можно превратить в 4.99999991 extented в регистре (повышение точности)
ОтветитьУдалить