| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Фокусы Delphi |
| Автор: Poseidon 10.3.2005, 03:41 | ||
Значит так друзья. Пишу программу и столкнулся с "детской" процедуркой. Код немного переделанный (что бы понятно было), но суть ясна. Значит вот он:
Так вот сколько вы ожидаете увидеть в Label1? А ожидал 3. А там 2! Вроде встречался с функцией Round и знаю, что она должна округлять по извесным правилам. Т.е. 0.5 округляется до 1, а 1.5 до 2. Но почему же тогда 1 + 2 = 2 ? Может кто встречался с таким? Это хорошо, что у меня так получилось, что я сразу нашел. А ведь из-за этого погут все расчеты пойти на смарку. |
| Автор: RA 10.3.2005, 04:40 | ||||
0.5 округляется до 0. Добавлено @ 04:45 попробуй вместо Round использовать Ceil, ибо чеил округляет число в сторону увеличения, а round до ближайшего целого.
|
| Автор: SPrograMMer 10.3.2005, 17:48 | ||||
Из того модуля Math:
Попробуй сказать:
|
| Автор: Poseidon 11.3.2005, 04:05 | ||||||
RAdmin
то получим не желанные 5, а 4!
Не подходит! Нужно именно округлять по правилам (< 5 в меншую, >=5 в большую сторону). Конечно можно устроить проверку символа после запятой и по нему определять, куда округлять в большую (Ceil) или меншую (Trunc) сторону. Но все же хотелось бы разобраться, почему так происходит? В общем-то начиная эту тему, я не ставил себе целью найти помощь. В Delphi есть ряд математических функций, каторые могут справится с округлением. Можно еще применить всякие хитрости (допустим, предложенная мной проверка символа после запятой). Целью было узнать, почему так происходит. Почему Round округляет не так, как от нее ждут? Есть у кого мнение по этому поводу? |
| Автор: <Spawn> 11.3.2005, 06:04 | ||
Это не ошбика Борладн это особенность представления дробных чисел в FPU, и, если я правильно помню, то именно от того, что 0.5(и некоторые другие, приведенные тобой числа), не могут быть представлены конечной двоичной дробью, в результате чего в реальности число ставновится чем то вроде - 0.499999999999999999999999999999999. Где то на этом форуме недавно была ссылка на статью, хорошо это обьясняющюю, но найти ее, к сожалению, я не могу. |
| Автор: Alex 11.3.2005, 09:47 | ||
http://forum.vingrad.ru/index.php?showtopic=44001&hl= |
| Автор: Akina 11.3.2005, 09:54 | ||
Хотя это - следствие представления числа в бине, но попутно замечу, что есть термин "бухгалтерское округление" - то что ОБЯЗАНО использоваться в любых денежных расчетах. Так вот, по нему половинка округляется не вниз и не вверх, а к БЛИЖАЙШЕМУ ЧЕТНОМУ. И это определено соотв. стандартом, международным кстати. Вот такие пироги... |
| Автор: RST8 11.3.2005, 20:59 |
| Так чем же можно округлить число по правилам до какого нибудь знака после запятой? |
| Автор: Петрович 11.3.2005, 22:13 | ||
Дык неужели из темы не стало ясно что все зависит от того какие правила имеются ввиду. Много их, правил-то, и все разные. |
| Автор: SPrograMMer 11.3.2005, 22:45 | ||||
У меня что-то родилось: Пусть наше 0.5 представляется в виде 0.499999999999999999999, а нам нужно всё это округлить до целых. Поступаем следующим образом: 1. Округлаем до того знака, до которого задавли число, то есть, в числе 0.5 одна цифра после запятой => округляем до одного знака после запятой (можно RondTo`ом воспользоваться). Вот только что при этом получится? по идее 0.49999999999999 должно превратиться в 0.5 2. Округлаем (тут же) полученное число до нужного.
|
| Автор: Петрович 12.3.2005, 00:40 | ||||
Посмотри описания функций RoundTo и SimpleRoundTo:
А если проще: Функции RoundTo и SimpleRoundTo используют несколько разные алгоритмы в случаях, когда округляемое число расположено точно посередине между двумя значениями, имеющими заданное число значащих разрядов. Функция RoundTo в этом случае округляет до четного числа. А функция SimpleRoundTo в этом случае округляет до большего числа. Так что выбирай то что тебе надо. |
| Автор: Santer 12.3.2005, 02:58 |
| Вот вам еще один способ округления: к округляемому числу прибавляем 0.5 и отбрасываем дробную часть |
| Автор: Poseidon 12.3.2005, 04:37 | ||
| Всем спасибо за ответы В заключении темы хотелось бы все-таки выяснить, так есть ли в Delphi функция, каторая выполняла бы то, что задокументировано для Round ? Т.е. функция, каторая округляла бы по общепринятым правилам, а не по каким-либо бухгалтерским или еще. Чтоб <?,5 округляло к меншему, а >=?.5 - к большему. Или все таки придется написать такую функцию самому? Santer
|
| Автор: Alex 12.3.2005, 10:57 | ||
Ты так и не понял проблемы. |
| Автор: Poseidon 12.3.2005, 20:17 | ||||||||||||||||
Alex
Это действительно проблема, т.к. в книге по Delphi написано буквально следующее:
Даже в справке Delphi написано
PS. Хотелось бы все таки узнать, есть ли та функция, что округлит 3,5 к 4 ("по известным правилам"). Как видно Round не справляется. Alex, лично к тебе: В одной из других тем (не так давно) ты писал следующее:
и
Как говорится: "Модератор всегда прав" (p0s0l) |
| Автор: Alex 12.3.2005, 21:23 |
| Poseidon, я насколько понимаю, ты меня обвиняешь в том, что я тебе отвечаю не полностью на твой вопрос. Прошу заметить, что я не участвую в обсуждении этой проблемы. Я только дал ссылку на статью, о которой упомянул один из участников. Как говорится, не знаю досконально вопроса и не лезу. |
| Автор: Alex 12.3.2005, 22:03 | ||
Полазил я тут по сети и нашел ответ на вопрос.
|
| Автор: Петрович 12.3.2005, 22:29 | ||||||||
А следующее предложение в хелпе переводить не пробовал? Тогда помогу я
Если X точно посередине между двумя числами, результат будет ЧЕТНЫМ числом.
Читайте внимательнее хелп!
Если имеются ввиду школьные правила, то читай внимательнее http://forum.vingrad.ru/index.php?showtopic=44984&view=findpost&p=348682 |
| Автор: Alex 12.3.2005, 22:41 | ||
| Poseidon, если ты задаешь вопрос, и тебе отвечают, то будь любезен проверять то, что тебе предлагают, а не орать на весь форум, что тебя обидели и все такие нехорошие. Держи свой код
|
| Автор: Poseidon 13.3.2005, 00:47 | ||||||||
Alex
Петрович
Огромное спасибо всем кто принял участие в обсуждении этой темы!!! Отдельное спасибо Петрович и Alex. В следующий раз буду по внимательнее. |
| Автор: amsoft 10.12.2009, 08:04 | ||
| Возвращаясь к старой теме: Недавно тоже столкнулся с такой некорректной работой функции Round. При округлении числа, дробная часть которого = 0.5 всегда возвращает четное число, это баг с точки зрения математики (тем более каждое неправильное округление в моем случае может обойтись в реальную "копеечку"). Но разработчикам дельфей видать не знакомы правила математики Я победил это так:
ЗЫ У меня D5, может в более поздних версиях нет такого бага |
| Автор: Демо 10.12.2009, 11:39 | ||||
amsoft,
Так что никакого глюка. В Help именно так и описано поведение Round. |
| Автор: amsoft 10.12.2009, 11:52 | ||
| Демо, я знаю - читал уже, но меня не устраивает такой метод округления. Кстати, раз уж его называют "Banker’s Rounding", то могли бы его засунуть в функцию типа BankerRound, а Round сделали бы нормальным. Чуть модернизировал, теперь работает с отрицательными числами тоже
ЗЫ Не побоюсь этого слова Smart |
| Автор: amsoft 10.12.2009, 12:53 |
| кстати, есть ли в делфях уже готовая подобная функция, чтобы велосипедостроительством не заниматься? |
| Автор: profesiachuvak 10.12.2009, 13:43 | ||||
Да какой тут велосипед, ранее предлогалось сделать так
Вот и весь велосипед. Округляй с помощью trunc() и получишь нормальное математическое округление по школьным правилам. |
| Автор: amsoft 10.12.2009, 15:01 |
| profesiachuvak, где-то в этой теме промелькала такая мысль, почему-то не обратил на нее внимание сразу Thx |
| Автор: Alexeis 10.12.2009, 15:06 |
| profesiachuvak, а если число отрицательное? |
| Автор: Beltar 10.12.2009, 18:27 | ||
trunc(3.9)=3, а не 4. Лучше уж frac(x)>0.5 проверять. |
| Автор: amsoft 10.12.2009, 18:30 | ||
| Alexeis, немного подшаманить можно:
Добавлено через 1 минуту и 2 секунды Beltar, а прибавлять 0.5 кто будет? |
| Автор: ~FoX~ 10.12.2009, 18:33 |
| Poseidon, Лениво читать весь тред, но имел счастья сталкнутся с обратной проблемой, вобшим не суть дело... Тип Currency даст тебе то что ты хочешь поиметь... |
| Автор: Beltar 10.12.2009, 18:35 | ||
Чего прибавлять??
Или я не прав: |
| Автор: Alexeis 10.12.2009, 18:38 |
Можно, но тут уже добавилось ветвление и конструкция перестала быть изящной. |
| Автор: amsoft 10.12.2009, 18:47 |
| Alexeis, ИМХО Без ветвления никуда Добавлено через 1 минуту и 17 секунд Beltar, главное результат ЗЫ мой прошлый велосипед с десятью колесами и двумя сиденьями в топку |
| Автор: bems 10.12.2009, 19:56 |
| Модератор: amsoft, не нужно откапывать старые темы. |
| Автор: amsoft 11.12.2009, 07:01 |
| bems, я вообще хотел создать новую тему, но нашел тему с похожей проблемой и решил "добить" ее до конца, ибо это меня тоже касается. В принципе с этим вопросом разобрались. Тема может быть закрыта. |
| Автор: Beltar 11.12.2009, 08:02 | ||
Что-то я туплю.
|
| Автор: bems 11.12.2009, 18:41 |
| amsoft, ну это так, на будущее. Если бы я увидел в этом нарушение, было бы предупреждение в личное дело. В данном случае поднятие топика оправдано, да. |