![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
Нитонисе |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 917 Регистрация: 5.11.2009 Репутация: нет Всего: 2 |
В моих программах часто выполняются различные расчеты. Нередко встречаются очень маленькие цифры (например первая значащая цифра появляется в десятом знаке после запятой) и мне нужна достаточная точность, что бы 0.00000000001 не стало вдруг нулем. Сейчас я всегда использую тип float и вижу что часто присваивая переменно например 1 на деле могу получить 1.999999856752. В подавляющем большинстве случаев это приемлемая точность, но тем не менее было бы здорово, если бы вычисления стали еще точнее. Поможет ли мне в этом double или этот тип всего лишь увеличивает емкость, позволяя использовать бОльшие числа?
|
|||
|
||||
boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
нет. создаст еще больше проблем. для подобных задач существует прекрасная и очень сильно проверенная библиотека GMP. ну или на худой конец, переходи на использование std::complex. |
|||
|
||||
Фантом |
|
|||
![]() Вы это прекратите! ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1516 Регистрация: 23.3.2008 Репутация: нет Всего: 49 |
Если механически везде поменять float на double, то где-то поможет, а где-то, наоборот, ухудшит ситуацию. При грамотном использовании - поможет. Но лучше давайте сразу отделим мух от котлет. Вам нужна относительная погрешность вычислений 10^{-10} или абсолютная погрешность 10^{-10} (с сравнительно большей относительной)? В первом случае без double не обойтись, во втором - float вполне может и хватить. |
|||
|
||||
kosmonaFFFt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 538 Регистрация: 14.4.2008 Где: Иннополис Репутация: нет Всего: 5 |
А чем поможет std::complex? Он ведь тоже базируется на double, float и т. д. -------------------- ![]() |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Лучше с самого начала везде использовать double - кроме массивов и других случаев, когда нужно экономить память.
Все функции из math.h работают с double - при их вызове float конвертируется в double, а результат наоборот. Регистры математического сопроцессора имеют тип long double, команды сохранения из его регистра в float и загрузки из float более медленные. Так что с double будет работать не только точнее, но и чуть быстрее. А если точности double не хватает - нужна специализированная библиотека. |
|||
|
||||
Alexeis |
|
|||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 12 Всего: 459 |
Не всегда поможет. Числа float и double имеют фиксированное число цифр. Например если к числу 9 000 000 прибавить 0. 000 009, то мы потеряем младшую часть, она будет попросту отброшена хоть то float, хоть то double. Бывает, что при вычислениях такие прибавления или умножения делаются в качестве промежуточных вычислений, а конечный результат малый. В этом случае можно получить погрешность в 1000% и больше. Кроме того на точность вычислений еще влияют настройки сопроцессора. Например при подключении DirectX автоматически снижается точность всех флоат вычислений и даже дабл будут считаться с точностью флоатов. Также потери точности легко добиться при возведении чисел в степень. Возвели в квадрат или куб, че нить прибавили, извлекли корень и младшие разряды пошли по бороде.
Добавлено через 4 минуты и 58 секунд
Если говорить в общем случае, то это неверно. Лично я работал с аппаратурой где флоат считался раз в 50 быстрее дабла, не говоря уже об операциях типа копирования массивов или о объеме занимаемой памяти. Кроме того операции с флоатами могут оптимизироваться на SSE и в результате получаем скорости много выше. -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
Нитонисе |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 917 Регистрация: 5.11.2009 Репутация: нет Всего: 2 |
А есть где-то обзор данной библиотеки на русском? И есть ли смысл полностью заменить float на данный тип? Речь идет о скорости вычислений и занимаемой памяти. Может быть уместно разделять задачи, где нужна повышенная точность и использовать там GMP и менее важные вычисления, где и float сойдет?
Мне нужна точность хотябы в 10-ом знаке после запятой, чего float не позволяет. Порой заведомо зная что в некоторой части вычислений будут малые числа я специально их увеличиваю в 100 000 раз, чтобы программа не сочла где-то что значением малого числа можно пренебречь и приравнять его к нулю, в результате чего бывает ошибка деления на ноль. Попутный вопрос. Имеет ли смысл увеличивать числа типа float с целью увеличения точности? Вот если записать float a=1, то можно получить a=0.99999957482. А если записать float a=100000, ведь не получится a=99999.957482, скорее что-то типа а=99999.99999957482. Это сообщение отредактировал(а) Нитонисе - 27.8.2012, 10:22 |
||||
|
|||||
Alexeis |
|
|||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 12 Всего: 459 |
- Нет. числа float отдельно хранят значащие цифры, отдельно степень. Просто увеличиться значение степени. float хранит 7-8 десятичных цифр. double что-то около 15-16. Чтобы сказать точнее нужно смотреть спецификацию. По степени запас флоата 10^38й степени. Точность в 10м знаке обеспечит только double (long double) и то если не будет операций умножения на большие числа или возведения в степень. Добавлено через 4 минуты и 41 секунду Можно кстати википедию почитать http://ru.wikipedia.org/wiki/%D0%A7%D0%B8%...%82%D0%BE%D0%B9 Более подробно описано. Это сообщение отредактировал(а) Alexeis - 27.8.2012, 10:37 -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
Фантом |
|
|||
![]() Вы это прекратите! ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1516 Регистрация: 23.3.2008 Репутация: нет Всего: 49 |
Вот меня и интересует, что Вы под этим понимаете. Вообще говоря, float позволяет работать с числами до 10^{-38}. только вот относительная погрешность будет плохой. Нет, это бессмысленно. Иногда можно добиться некоторого улучшения точности, добившись того, чтобы все числа были близки к 1, но вот обратный процесс ничего полезного не даст. P.S. Кстати, полезно иметь в виду, что 99% проблем такого рода решаются не выбором типов, библиотек и т.п., а разумным преобразованием алгоритма вычислений. |
|||
|
||||
Нитонисе |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 917 Регистрация: 5.11.2009 Репутация: нет Всего: 2 |
||||
|
||||
Alexeis |
|
||||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 12 Всего: 459 |
Относительная погрешность постоянная. Она вычисляется как отношение погрешности к самой величине. Величина увеличилась, ну так и погрешность увеличилась пропорционально, а отношение сохранилось. Добавлено @ 11:54
Так и будет. Числа с плавающей точкой как раз для этого. Вопрос лишь сколько значащих цифр нужно сохранять. -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
||||
|
|||||
Нитонисе |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 917 Регистрация: 5.11.2009 Репутация: нет Всего: 2 |
||||
|
||||
Фантом |
|
|||
![]() Вы это прекратите! ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1516 Регистрация: 23.3.2008 Репутация: нет Всего: 49 |
float для этого более чем достаточно. Ну да, правильно. А что, собственно, Вы планировали получить? Операнды имеют относительную погрешность около 10^{-6}, при перемножении относительные погрешности складываются, соответственно, относительная погрешность результата имеет тот же порядок. Добавлено через 2 минуты и 5 секунд Не совсем. На границах возможных значений типа относительная погрешность в любом случае будет расти. |
|||
|
||||
Нитонисе |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 917 Регистрация: 5.11.2009 Репутация: нет Всего: 2 |
А планировал получить 1 Е-20 ![]() |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
В float под мантиссу выделяется 23 бита, это 6 знаков с небольшим запасом в десятичной системе. При умножении относительная погрешность удваивается. Вот и получаете 6 знаков точности. У long double - мантисса 64 бита, примерно 18 знаков точность. больше без спец. библиотеки не получите. Денежные суммы можно хранить в копейках вместо рублей, чтобы не было ошибок округления, В других случаях умножение на коэффициент обычно не поможет. Если решаешь уравнение: X^2 + 2000*X + 1 = 0; X1 = 1000 + sqrt(999999); X2 = 1000 - sqrt(999999); X2 лучше вычислять по формуле X2 = 1 / X1; |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |