Здравствуйте, -Cheese-, Вы писали:
C>Здравствуйте, np9mi7, Вы писали:
N>>Здравствуйте, -Cheese-, Вы писали:
C>>>Я понимаю, что типа хранение чисел с плавающей точкой и всё такое... но как избежать этого?
N>>Например использовать целочисленую арифметику до самого последнего момента;
C>>>Получаем: C>>>z1=4053.0000000 C>>>z2=4052.0000000
N>>А что должны получить? C>4052.0000000
C>Объясняю смысл проблемы... C>есть некоторые платежи для человека в некоторой валюте , C>например C>1) 5.09 C>2) 31.091 C>3) 1.01 C>......
C>и есть итоговая сумма — например: 37.191 C>но с человека нужно брать в этом случае 37.20 = ceil(sum(x_i)), x_i — i-тый платёж
C>на может сложиться ситуация когда человек должен заплатить например ровно 12 у.е., C>а ceil(sum(x_i)) может равняться 12.01 у.е., что не есть хорошо...
Где только вас учили метематике!!
Простейшее округление делается так:
E — поправочный коэффициент = 0.5
M — множитель равный 10 в степени N(где N количество знаков после запятой)
S — число которое нужно округлить.
R — результат.
R = (floor(S * M + E)) * M, либо
R = (ceil(S * M — E)) * M
Здравствуйте, <Аноним>, Вы писали:
А>Где только вас учили метематике!! А>Простейшее округление делается так: А>E — поправочный коэффициент = 0.5 А>M — множитель равный 10 в степени N(где N количество знаков после запятой) А>S — число которое нужно округлить.
А>R — результат. А>R = (floor(S * M + E)) * M, либо А>R = (ceil(S * M — E)) * M
Где меня только не учили математике... последний раз меня подучили на работе.
А ещё есть ТЗ, где ясно сказано, что даже при E=0.000000000000000000000000000000000000000001
результат округления x+E будет x+1, где х принадлежит множеству целых неотрицательных чисел (в данном случае)...
вот
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Округление с помощью ceil...
От:
Аноним
Дата:
18.10.06 06:35
Оценка:
Здравствуйте, -Cheese-, Вы писали:
C>Здравствуйте, <Аноним>, Вы писали:
А>>Где только вас учили метематике!! А>>Простейшее округление делается так: А>>E — поправочный коэффициент = 0.5 А>>M — множитель равный 10 в степени N(где N количество знаков после запятой) А>>S — число которое нужно округлить.
А>>R — результат. А>>R = (floor(S * M + E)) * M, либо А>>R = (ceil(S * M — E)) * M
C>Где меня только не учили математике... последний раз меня подучили на работе. C>А ещё есть ТЗ, где ясно сказано, что даже при E=0.000000000000000000000000000000000000000001 C>результат округления x+E будет x+1, где х принадлежит множеству целых неотрицательных чисел (в данном случае)... C>вот
Опечатался. Вот так будет правильно.
R = (floor(S * M + E)) / M, либо
R = (ceil(S * M — E)) / M
Здравствуйте, -Cheese-, Вы писали:
C>Вообще-то все расчёты и ведутся в копейках, но увы может быть такое, что нужно нецелое число копеек (например обмен валюты по курсу 5.065234152).
Представляю себе надпись на Сбер. Банке "Курс валют: 1 $ = 26.9445065234152 руб.";
Может можно держать курс целым числом 1 Цент = Целое Коэффициент * 1 Копейку? Или если всё это дело обобщить, то необходимо научиться переводить Условные Единицы одной валюты (Копейка, десятая часть копейки, сотая часть копейки...) в Условные Единицы другой вылюты (Цент, десятая часть цента, сотая часть цента...) с помощью Целого Коэффициента;
В итоге сумму счета получать по формуле:
Сумма = Количество У.Е. * 10 ^ Экспонента Валюты;
Экспонента Валюты это -2 для копеек, -3 для десятой части копейки, -4 для сотой части копейки...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Здравствуйте, <Аноним>, Вы писали:
А>Тогда со спокойной совестью приводите к типу int и смело прибавляйте 1, так как тип double всегда что-то там имеет в хвосте.
Тут... Re[2]: Округление с помощью ceil...
Здравствуйте, -Cheese-, Вы писали:
C>Вообще-то все расчёты и ведутся в копейках, но увы может быть такое, что нужно нецелое число копеек (например обмен валюты по курсу 5.065234152).
Ну что же, значит вот в этом месте и нужно умножать фиксированное на плавающее и получать фиксированное, причём по тому закону, который требуется — а не по тому, который забит в FPU.
Возможно, придётся поддержать несколько фиксированных форматов — *10^-2 (валюты) и *10^-9 (коэффициенты).
Либо плавающую арифметику с целой мантиссой и десятичным порядком.
Здравствуйте, -Cheese-, Вы писали:
C>Здравствуйте, Кодт, Вы писали: К>>Здравствуйте, -Cheese-, Вы писали: C>>>объясни попробуй клиенту про двоичное представление числа с плавающей точкой много нового о себе услышишь C>>>ну да ладно... будем вводить эпсилон промежуток К>>А может быть, сделать арифметику с фиксированной точкой? Грубо говоря, считать всё в int64 в копейках.
C>Вообще-то все расчёты и ведутся в копейках, но увы может быть такое, что нужно нецелое число копеек (например обмен валюты по курсу 5.065234152).
А числа плавающей запятой всё равно ничего не решат, только усугубят, т.к. точность всё равно конечная. Т.е. любой курс конвертации и сумму точно всё равно не представишь. Всё равно не каждое число можно ровно поделить на 2 части. Всё равно если с числом попроизводить какие-то вычисления и ожидать получить ровно 2,9, можешь получить 3,1.
Здравствуйте, <Аноним>, Вы писали:
Axc>>Я бы делал так: Axc>>
Axc>> const double accuracy = 1E-6;
Axc>> double x = 800.0;
Axc>> double y = 5.065;
Axc>> double z1 = ceil(x * y * (1 - accuracy));
Axc>> double z2 = x * y;
Axc>> double z3 = floor(x * y * (1 + accuracy));
Axc>>
А>1) почему accuracy = 1E-6
Ни почему. Постановка задачи на тот момент еще не была уточнена. Соответственно, нужная точность была взята с потолка и задана константой. Вообще же, данный способ годится для научных расчетов, но не для денег. А>2) почему в одном случае 1-accuracy, а в другом 1+accuracy.
Потому что ceil надо брать от числа чуть меньшего, а floor от чуть большего.