| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Общие вопросы по .NET и C# > Проблемма с double |
| Автор: FREEDEV 4.5.2008, 16:43 |
| Добрый день! Возникла проблеммка с double. Операции умножения, деления приводят к появлению лишних знаков после запятой, например: 3*0.01 возвращает что, то вроде 0.030000001 5*0.02 = 0.0499999998 Немогу разобраться в чем дело, может кто встречался с подобным |
| Автор: jonie 4.5.2008, 17:04 |
| дело в машинном представлении чисел с плавающей запятой в компьютере. погугли, там все очень неплохо написано.... вкратце : потому что компьютер сохраняет число как 2^М |
| Автор: source777 4.5.2008, 21:49 |
| Интересно сколько миллионов раз этот вопрос задавался? P.S. FREEDEV, открой для себя округление... |
| Автор: Lycifer 5.5.2008, 17:11 |
| округление хорошо ну вот если нужно посчитать точное значение? |
| Автор: mr.DUDA 5.5.2008, 17:37 |
| Округлять по-разному можно, например до 8-го знака после запятой. |
| Автор: source777 5.5.2008, 21:03 |
| Точные значения в обыкновенных дробях считаются, а не в десятичных, это ещё в 5-ом классе средней школы проходят, тут даже механизмы хранения вещественных чисел в памяти компьютера непричём... |
| Автор: amarenkov 6.5.2008, 07:59 |
Можно еще при расчетах использовать преобразование в другую систему счисления. В моем проекте, например, в одном месте из-за таких же проблем используются вычисления над 64-разрядными целыми числами. Правда это не я делал, но автор уверяет, что избавился от многих проблем |
| Автор: Lycifer 6.5.2008, 12:23 |
| Нет округление не пойдёт, просто сдесь приведёт пример когда значение уменьшается(то и есть его нужно увеличить), бываю сдучаи года 123.00000017 послу огругления будем иметь 123.0000002, ну или 123.0000001, а когда прибавим 0.00000001 будет совсем другое значения вобщемто очень приблезительное, единственное что вижу, так это то что можно реализовать класс, но он будет совсем не производителен!! |
| Автор: Дрон 6.5.2008, 13:18 |
| Lycifer, используй тип decimal. |
| Автор: source777 6.5.2008, 16:11 |
| не бывает таких случаев, если ты их сам специально не создаёшь, так что не гони... |
| Автор: mr.DUDA 6.5.2008, 17:45 |
| Дрон, только вот тормознутый он, этот decimal, жутко... А так конечно если бывает что вылезет погрешность, нужно её округлять. Других вариантов нет, AFAIK. |
| Автор: Дрон 6.5.2008, 19:28 |
Ну так про требования к быстродействию автор ничего не сказал |
| Автор: source777 6.5.2008, 21:37 |
| Как же нет, я уже ещё 1 вариант назвал - вычисление в обычных дробях, так практически все математические пакеты поступают и никаких проблем с погрешностями не знают... другой вопрос, что это на много порядков более сложная задача, чем простое округление... |
| Автор: jonie 6.5.2008, 23:30 |
| не все числа представляются в виде обыкновенных дробей.... и такая задача становится еще сложнее) и мат пакеты страдают порой и очень сильно от погрешности... сам один раз попал на это в матГаде.. тогда как Maple посчитал лучше (ну а руками так вообще хорошо посчиталось)).... |
| Автор: mr.DUDA 9.5.2008, 20:32 |
| source777, трабл в том что обычно нужен ввод исходных данных в виде строки. И тут ты хоть колом на голове теши, не сможешь перевести все возможные числа, введённые пользователем, из формата floating point в формат делимое/делитель. Ну вот введу я к примеру "1,01928" и напиши алгоритм вычисляющий сабж. |
| Автор: source777 9.5.2008, 20:56 | ||
Алгоритм: 1) выяснить сколько цифр после запятой ввёл пользователь, равно m 2) числитель = k = исх.число * 10^m 3) знаменатель = n = 10 ^ m 4) по алгоритму Евклида находим НОД(k; n) 5) сокращаем и получаем обыкновенную дробь, "введённую" пользователем. |
| Автор: FREEDEV 12.5.2008, 13:39 |
| Давненько я сюда не заглядывал, спасибо всем за ответы. Действительно числа представлены в компьютере степенями двойки, поэтому в Debugeре видна была подобная картина, результат же выводимый пользователю, имел нормальный вид. За исключением значений массива в сумме дававших 0, тогда возвращаемым значением было что-то наподобие указанного выше, поправил округлением. |
| Автор: Lycifer 14.5.2008, 10:05 |
| source777 Это конечно хорошо использовать дробь, тока есть такой вопрос, как же быть если приходится передавать в функции и конечно получать результаты(sin, cos...)? |
| Автор: source777 14.5.2008, 14:00 | ||
P.S. Не забывай, что любая математическая функция может быть представлена в виде суммы ряда обыкновенных дробей, причём функцию, представленную в таком виде, можно вычислить с любой точностью, а точность задаётся когда запрашивается результат, тогда же и происходят реальные вычисления... |