| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Округление |
| Автор: Burka 20.1.2010, 15:22 | ||
| Давно бьюсь над процедурой округления, которая будет правильно округлять все числа, по школьному правилу. Сейчас использую такую процедуру.
Не давно нашел такой баг в ней при округлении допустим числа -12.15 до десятых получаем -12.2 (правильно) но округляя -22.15 получаем -22.1 (не правильно) Подскажите есть ли стабильные процедуры для этого или может что в моей исправить |
| Автор: XperT 21.1.2010, 14:52 |
| Посмотри в сторону Math.SimpleRoundTo |
| Автор: Burka 25.1.2010, 09:51 |
| пока округляю с помощью FormatFloat и вроде норм |
| Автор: shmelina 27.1.2010, 02:49 |
| SimpleRoundTo тоже неправильно округляет. Сам проверил. Вообще с округлением не все так просто. Я когда прочитал эту статью, мне плохо стало: Загадки округления. http://www.delphikingdom.com/asp/viewitem.asp?catalogID=1217 Я пока остановился на этом способе: Trunc(Value * 100 + 0.5) / 100 |
| Автор: Burka 28.1.2010, 11:27 | ||
shmelina, спасибо тоже попробовал твой метод, отрицательные числа он не правильно округляет я немного доработал) лишь бы работало)
А вообще надо найти или написать уже корректную процедурку |
| Автор: shmelina 28.1.2010, 15:31 |
| Число 1.15 округляется до 1.1 |
| Автор: shmelina 28.1.2010, 17:11 | ||||||
| Странно. Поднял свои исследования на тему округления. Даже тогда написал специальную программу, которая округляет разными способами. И точно помню, что пришел к выводу, что есть проблемы с функцией SimpleRoundTo. Проверял на D2009. Но сейчас не могу вспомнить какие именно. Сейчас все пробую и вроде все правильно работает. Единственное, что нашел, что в D7 реализация функции SimpleRoundTo на отрицательных числах будет ошибочная:
В более поздних версиях (турбо (2006), 2007) сделали уже правильно:
Если смотреть на исследования в статье, то такое ощущение, что в функции SimpleRoundTo не было "+ 0.5". Может в патче потом добавили? Сейчас не важно. Пока такой вывод: функция SimpleRoundTo работает правильно, если она такая:
Верно? |
| Автор: shmelina 28.1.2010, 19:11 | ||||||
| Так. Снова погрузился в проблемы округления. Вот что выяснилось на этот раз: Результаты округления зависят 1. от типа данных переменной, которую округляем. 2. от типа данных параметров функции округления SimpleRoundTo. В Delphi 2007 функция объявлена так: function SimpleRoundTo(const AValue: Double; const ADigit: TRoundToRange = -2): Double; В Delphi 2010 функция объявлена так: function SimpleRoundTo(const AValue: Extended; const ADigit: TRoundToRange = -2): Extended; Вроде бы тип данных сменился и только! Но как оказалось это влияет на результат - смотря что вы в нее передадите. И так я протестировал две реализации функции SimpleRoundTo (Double и Extended) и округление прямо в коде: Trunc(Value * 10 + 0.5) / 10. Тестировал на Delphi 2010. Три разных типа данных: Currenty, Double и Extended. Округлял число 1.15 до одного знака после запятой. Вот что получилось:
А вот с числом 1,25
С отрицательными числами такая же картина. Вывод: 1. Переменную типа Double с помощью функции SimpleRoundTo корректно округлить нельзя. 2. Переменную любого типа с помощью функции SimpleRoundTo, где параметр передается как Double, корректно округлить нельзя. Короткий вывод: Не используйте Double в округлениях Вот код, которым я все это проверил. Положите на форму StringGrid и дайте ему имя sg.
Не судите строго, если я где-то ошибся в своих исследованиях. Поправьте. |
| Автор: Burka 4.3.2010, 15:15 | ||||
Я думаю логичнее было бы не использовать SimpleRoundTO ^^ и вообще лучше ничего не использовать из стандартных процедур для округления при серъезных подсчетах где важны погрешности. А вообще я сейчас пользуюсь этим, и радуюсь) Юзеры не приходили пока с жалобами)
вообще она возращала строковую но мне не удобно так) |