Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Фокусы Delphi, Простая функция Round фокуснечает. 
:(
    Опции темы
Poseidon
  Дата 10.3.2005, 03:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Значит так друзья. Пишу программу и столкнулся с "детской" процедуркой. Код немного переделанный (что бы понятно было), но суть ясна. Значит вот он:
Код
var
str: string;
x,y: real;
begin
x:= 0.5;
y:= 1.5;
str:= IntToStr( Round(x) + Round(y) );
Label1.Caption:= str ;
end;

Так вот сколько вы ожидаете увидеть в Label1? А ожидал 3. А там 2!
Вроде встречался с функцией Round и знаю, что она должна округлять по извесным правилам. Т.е. 0.5 округляется до 1, а 1.5 до 2. Но почему же тогда 1 + 2 = 2 ?
Может кто встречался с таким? Это хорошо, что у меня так получилось, что я сразу нашел. А ведь из-за этого погут все расчеты пойти на смарку. smile


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
RA
Дата 10.3.2005, 04:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Брутальный буратина
****


Профиль
Группа: Участник Клуба
Сообщений: 3497
Регистрация: 31.3.2002
Где: Лес

Репутация: 14
Всего: 115



Цитата(Poseidon @ 10.3.2005, 03:41)
Т.е. 0.5 округляется до 1


0.5 округляется до 0.

Добавлено @ 04:45
попробуй вместо Round использовать Ceil, ибо чеил округляет число в сторону увеличения, а round до ближайшего целого.


Код


... модуль Math

//Округление в сторону увеличения
function Ceil(const X: Extended): Integer;
begin
  Result := Integer(Trunc(X));
  if Frac(X) > 0 then
    Inc(Result);
end;

//Округление в сторону уменьшения
function Floor(const X: Extended): Integer;
begin
  Result := Integer(Trunc(X));
  if Frac(X) < 0 then
    Dec(Result);
end;



Это сообщение отредактировал(а) RAdmin - 10.3.2005, 04:56
PM   Вверх
SPrograMMer
Дата 10.3.2005, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Спамер :)
**


Профиль
Группа: Участник
Сообщений: 442
Регистрация: 5.11.2004
Где: Краснодар

Репутация: 2
Всего: 6



Из того модуля Math:
Код

Function RoundTo(const AValue:Double;const ADigit:TRoundToRange):Double;

Попробуй сказать:
Код

...
str:= IntToStr( RoundTo(x,0) + RoundTo(y,0) );
...



--------------------
животное = зверь
законченный гентушник
PM MAIL ICQ Jabber   Вверх
Poseidon
Дата 11.3.2005, 04:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



RAdmin
Цитата
0.5 округляется до 0.
Это в этой процедуре. А если мы, к примеру, возьмем
Код
x:= 1.5;
y:= 2.5;

то получим не желанные 5, а 4!
Цитата
попробуй вместо Round использовать Ceil

Не подходит! Нужно именно округлять по правилам (< 5 в меншую, >=5 в большую сторону). Конечно можно устроить проверку символа после запятой и по нему определять, куда округлять в большую (Ceil) или меншую (Trunc) сторону. Но все же хотелось бы разобраться, почему так происходит? smile Ведь по правилам 0,5 округляется до 1. А Delphi округляет до 0. При этом 1,5 округляется до 2 и 2,5 до 2 !!! 3,5 до 4 и 4,5 до 4 !!! И так далее. Что это? Ошибка Borland? Или какая-то неизвестная тонкость функции Round?

В общем-то начиная эту тему, я не ставил себе целью найти помощь. В Delphi есть ряд математических функций, каторые могут справится с округлением. Можно еще применить всякие хитрости (допустим, предложенная мной проверка символа после запятой). Целью было узнать, почему так происходит. Почему Round округляет не так, как от нее ждут?

Есть у кого мнение по этому поводу?


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
<Spawn>
Дата 11.3.2005, 06:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Око кары:)
****


Профиль
Группа: Экс. модератор
Сообщений: 2776
Регистрация: 29.1.2003
Где: Екатеринбург

Репутация: 44
Всего: 64



Цитата
Целью было узнать, почему так происходит. Почему Round округляет не так, как от нее ждут?

Это не ошбика Борладн это особенность представления дробных чисел в FPU, и, если я правильно помню, то именно от того, что 0.5(и некоторые другие, приведенные тобой числа), не могут быть представлены конечной двоичной дробью, в результате чего в реальности число ставновится чем то вроде - 0.499999999999999999999999999999999.

Где то на этом форуме недавно была ссылка на статью, хорошо это обьясняющюю, но найти ее, к сожалению, я не могу.

Это сообщение отредактировал(а) <Spawn> - 11.3.2005, 06:06


--------------------
"Для некоторых людей программирование является такой же внутренней потребностью, подобно тому, как коровы дают молоко, или писатели стремятся писать" - Николай Безруков.
PM MAIL ICQ   Вверх
Alex
Дата 11.3.2005, 09:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 80
Всего: 162



Цитата
Где то на этом форуме недавно была ссылка на статью, хорошо это обьясняющюю, но найти ее, к сожалению, я не могу.

http://forum.vingrad.ru/index.php?showtopic=44001&hl=


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Akina
Дата 11.3.2005, 09:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: нет
Всего: 454



Цитата(Poseidon @ 11.3.2005, 05:05)
При этом 1,5 округляется до 2 и 2,5 до 2 !!! 3,5 до 4 и 4,5 до 4 !!! И так далее. Что это? Ошибка Borland? Или какая-то неизвестная тонкость функции Round?

Хотя это - следствие представления числа в бине, но попутно замечу, что есть термин "бухгалтерское округление" - то что ОБЯЗАНО использоваться в любых денежных расчетах. Так вот, по нему половинка округляется не вниз и не вверх, а к БЛИЖАЙШЕМУ ЧЕТНОМУ. И это определено соотв. стандартом, международным кстати. Вот такие пироги...


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
RST8
Дата 11.3.2005, 20:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 232
Регистрация: 8.12.2004

Репутация: 1
Всего: 1



Так чем же можно округлить число по правилам до какого нибудь знака после запятой?
--------------------
Посадка, с места которой можно уйти на собственных ногах, считается удачной!
PM   Вверх
Петрович
Дата 11.3.2005, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1000
Регистрация: 2.12.2003
Где: Москва

Репутация: 25
Всего: 55



Цитата(RST8 @ 11.3.2005, 21:59)
Так чем же можно округлить число по правилам до какого нибудь знака после запятой?

Дык неужели из темы не стало ясно что все зависит от того какие правила имеются ввиду. Много их, правил-то, и все разные.



--------------------
Все знать невозможно, но хочется
PM ICQ   Вверх
SPrograMMer
Дата 11.3.2005, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Спамер :)
**


Профиль
Группа: Участник
Сообщений: 442
Регистрация: 5.11.2004
Где: Краснодар

Репутация: 2
Всего: 6



Цитата
Дык неужели из темы не стало ясно что все зависит от того какие правила имеются ввиду. Много их, правил-то, и все разные.

smile
У меня что-то родилось:
Пусть наше 0.5 представляется в виде 0.499999999999999999999, а нам нужно всё это округлить до целых. Поступаем следующим образом:
1. Округлаем до того знака, до которого задавли число, то есть, в числе 0.5 одна цифра после запятой => округляем до одного знака после запятой (можно RondTo`ом воспользоваться).
Вот только что при этом получится? по идее 0.49999999999999 должно превратиться в 0.5
2. Округлаем (тут же) полученное число до нужного.

Код

  X:=0.5;
  Y:=Round(RoundTo(X,-1));  // оч хочется что б в y стало 1.




--------------------
животное = зверь
законченный гентушник
PM MAIL ICQ Jabber   Вверх
Петрович
Дата 12.3.2005, 00:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1000
Регистрация: 2.12.2003
Где: Москва

Репутация: 25
Всего: 55



Посмотри описания функций RoundTo и SimpleRoundTo:

Цитата
RoundTo uses “Banker’s Rounding” to determine how to round values that are exactly midway between the two values that have the desired number of significant digits. This method rounds to an even number in the case that AValue is not nearer to either value.

The following examples illustrate the use of RoundTo:

Expression Value

RoundTo(1234567, 3) 1234000
RoundTo(1.234, -2) 1.23
RoundTo(1.235, -2) 1.24
RoundTo(1.245, -2) 1.24

Note: The behavior of RoundTo can be affected by the Set8087CW procedure or SetRoundMode function.

Цитата
SimpleRoundTo uses asymmetric arithmetic rounding to determine how to round values that are exactly midway between the two values that have the desired number of significant digits. This method always rounds to the larger value.

The following examples illustrate the use of SimpleRoundTo:

Expression Value

SimpleRoundTo(1234567, 3) 1234000
SimpleRoundTo(1.234, -2) 1.23
SimpleRoundTo(1.235, -2) 1.24
SimpleRoundTo(-1.235, -2) -1.23


А если проще:

Функции RoundTo и SimpleRoundTo используют несколько разные алгоритмы в случаях, когда округляемое число расположено точно посередине между двумя значениями, имеющими заданное число значащих разрядов. Функция RoundTo в этом случае округляет до четного числа. А функция SimpleRoundTo в этом случае округляет до большего числа.

Так что выбирай то что тебе надо.



--------------------
Все знать невозможно, но хочется
PM ICQ   Вверх
Santer
Дата 12.3.2005, 02:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 10.3.2005

Репутация: нет
Всего: нет



Вот вам еще один способ округления: к округляемому числу прибавляем 0.5 и отбрасываем дробную часть
PM MAIL   Вверх
Poseidon
Дата 12.3.2005, 04:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Всем спасибо за ответы smile
В заключении темы хотелось бы все-таки выяснить, так есть ли в Delphi функция, каторая выполняла бы то, что задокументировано для Round ? Т.е. функция, каторая округляла бы по общепринятым правилам, а не по каким-либо бухгалтерским или еще. Чтоб <?,5 округляло к меншему, а >=?.5 - к большему. Или все таки придется написать такую функцию самому?


Santer
Цитата
Вот вам еще один способ округления: к округляемому числу прибавляем 0.5 и отбрасываем дробную часть
Интересный способ. Как говорится, все гениальное - просто. Не плохо начал (это ведь твое парвое сообщение)! Так и держи.


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
Alex
Дата 12.3.2005, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 80
Всего: 162



Цитата(Poseidon @ 12.3.2005, 04:37)
В заключении темы хотелось бы все-таки выяснить, так есть ли в Delphi функция, каторая выполняла бы то, что задокументировано для Round ? Т.е. функция, каторая округляла бы по общепринятым правилам, а не по каким-либо бухгалтерским или еще. Чтоб <?,5 округляло к меншему, а >=?.5 - к большему. Или все таки придется написать такую функцию самому?

Ты так и не понял проблемы.


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Poseidon
Дата 12.3.2005, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Alex
Цитата
Ты так и не понял проблемы.
Пожет быть и не понял полностью. Вот что понял, так это то, что Round не округлит так, как в школах учат. Может потому, что
Цитата
половинка округляется не вниз и не вверх, а к БЛИЖАЙШЕМУ ЧЕТНОМУ
может потому, что
Цитата
0.5(и некоторые другие, приведенные тобой числа), не могут быть представлены конечной двоичной дробью, в результате чего в реальности число ставновится чем то вроде - 0.499999999999999999999999999999999.
может еще по какой причине.
Это действительно проблема, т.к. в книге по Delphi написано буквально следующее:
Цитата
  Функция Round(n) возврещает целое, полученное путем округления n по известным правилам
Может быть следует задать авторам этой книги вопрос, а что значит "известные правила"? Думаю это будет лишним. Если спросить у любого школьника (старших классов): "К чему округлиться 3,5?", то он сразу же ответит к 4." А к чему округлиться 3,4?" - "К трем." Это я думаю и есть известные правила.
Даже в справке Delphi написано
Цитата
Round returns an Int64 value that is the value of X rounded to the nearest whole number
На сколько я понял, перевод этого звучит так: "Round возвращает значение Int64, каторое является значением Х, округленным к самому близкому целому числу. Коментарии я думаю излишни.

PS. Хотелось бы все таки узнать, есть ли та функция, что округлит 3,5 к 4 ("по известным правилам"). Как видно Round не справляется.
Alex, лично к тебе: В одной из других тем (не так давно) ты писал следующее:
Цитата
А я в душе человек ленивый и ужасно не люблю изобретать велосипеды я ищу уже написанное стандартное и им пользуюсь (хотя иногда на поиски уходит не один месяц  ).
Так вот подскажи, может нашел что? Или может в FAQ что-нибудь есть по этому поводу? Написать такую функцию не проблема, но
Цитата
Дело в том, что достаточно грамотные и знающие программиста порой не знают о существовании таких нужных и полезных функций. Но их можно понять, эти функции появились в Delphi не так давно, по-моему, начиная с 5 версии

и
Цитата
Если уж учить так, учить и если показывать пример то самый правильный и может быть самый навороченный, но в нем учтены все подводные камни, о которых вам известно.


Как говорится: "Модератор всегда прав" (p0s0l)

Это сообщение отредактировал(а) Poseidon - 12.3.2005, 20:21


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
Alex
Дата 12.3.2005, 21:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 80
Всего: 162



Poseidon, я насколько понимаю, ты меня обвиняешь в том, что я тебе отвечаю не полностью на твой вопрос. Прошу заметить, что я не участвую в обсуждении этой проблемы. Я только дал ссылку на статью, о которой упомянул один из участников. Как говорится, не знаю досконально вопроса и не лезу.


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Alex
Дата 12.3.2005, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 80
Всего: 162



Полазил я тут по сети и нашел ответ на вопрос.
Цитата
После  Set8087CW(Default8087CW or $0800) Round(2.5) возвращает 3, а Round(3.5) - 4. А после Set8087CW(Default8087CW and $F7FF)  Round(2.5) возвращает 2, а Round(3.5) - 4(т.н. "банковское округление"). По умолчанию этот флаг сброшен, т.е. работает "банковское округление".(Проверял на D3 и W98)
Когда я впервые с этим столкнулся, то подумал, что это "происки империалистов":o). Но с удивлением обнаружил в "Правилах округления": "Если отбрасываемая цифра 5, а за ней нет значащих цифр, то округление производится на ближайшее четное число"(© М.Я. Выгодский, "Справочник по элементарной математике", М., 1966)



--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Петрович
Дата 12.3.2005, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1000
Регистрация: 2.12.2003
Где: Москва

Репутация: 25
Всего: 55



Цитата(Poseidon @ 12.3.2005, 21:17)
Даже в справке Delphi написано
Цитата
Round returns an Int64 value that is the value of X rounded to the nearest whole number

На сколько я понял, перевод этого звучит так: "Round возвращает значение Int64, каторое является значением Х, округленным к самому близкому целому числу. Коментарии я думаю излишни.

А следующее предложение в хелпе переводить не пробовал? Тогда помогу я smile
Цитата
If X is exactly halfway between two whole numbers, the result is always the even number.

Если X точно посередине между двумя числами, результат будет ЧЕТНЫМ числом.


Цитата(Poseidon @ 12.3.2005, 21:17)
Как видно Round не справляется.

Читайте внимательнее хелп!

Цитата(Poseidon @ 12.3.2005, 21:17)
PS. Хотелось бы все таки узнать, есть ли та функция, что округлит 3,5 к 4 ("по известным правилам").

Если имеются ввиду школьные правила, то читай внимательнее мой пост выше


--------------------
Все знать невозможно, но хочется
PM ICQ   Вверх
Alex
Дата 12.3.2005, 22:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 80
Всего: 162



Poseidon, если ты задаешь вопрос, и тебе отвечают, то будь любезен проверять то, что тебе предлагают, а не орать на весь форум, что тебя обидели и все такие нехорошие.

Держи свой код smile
Код

var
  str: string;
  x,y: real;
begin
  x:= 0.5;
  y:= 1.5;
  str:= FloatToStr(SimpleRoundTo(x, 0) + SimpleRoundTo(y, 0));
  ShowMessage(str);
end;



--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Poseidon
Дата 13.3.2005, 00:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Alex
Цитата
насколько понимаю, ты меня обвиняешь в том, что я тебе отвечаю не полностью на твой вопрос.
Цитата
если ты задаешь вопрос, и тебе отвечают, то будь любезен проверять то, что тебе предлагают, а не орать на весь форум, что тебя обидели и все такие нехорошие.
Принашу свои извенения, если кого-то ненароком зацепил словом или обидел. Я этого не хотел.
Цитата
а не орать на весь форум, что тебя обидели и все такие нехорошие
Вообще-то такого не было! Но я еще раз извеняюсь, если что-то написал не так.

Петрович
Цитата
Читайте внимательнее хелп!
Вот уж точно: "поспешишь - людей насмешишь". Да, во внимательность сила!

Огромное спасибо всем кто принял участие в обсуждении этой темы!!! Отдельное спасибо Петрович и Alex. В следующий раз буду по внимательнее.


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
amsoft
Дата 10.12.2009, 08:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 201
Регистрация: 17.10.2009
Где: KZ, Astana

Репутация: 3
Всего: 4



Возвращаясь к старой теме:

Недавно тоже столкнулся с такой некорректной работой функции Round.
При округлении числа, дробная часть которого = 0.5 всегда возвращает четное число, это баг с точки зрения математики (тем более каждое неправильное округление в моем случае может обойтись в реальную "копеечку"). Но разработчикам дельфей видать не знакомы правила математики  smile 
Я победил это так:

Код

function MyRound(X: Real): Integer;
begin
Result := Trunc(X);
if (X - Result) >= 0.5 then Result := Result + 1;
end;


ЗЫ У меня D5, может в более поздних версиях нет такого бага
--------------------
"Кто бы ты ни был - не думай о себе слишком"Дельфин
PM   Вверх
Демо
Дата 10.12.2009, 11:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 3.11.2005

Репутация: 30
Всего: 50



amsoft

Код

If X is exactly halfway between two whole numbers, the result is always the even number. 
This method of rounding is often called “Banker’s Rounding”.


Код

Round half to even

A tie-breaking rule that is even less biased is round half to even, namely
If the fraction of y is 0.5, then q is the even integer nearest to y.

Thus, for example, +23.5 becomes +24, +22.5 becomes +22, -22.5 becomes -22, and -23.5 becomes -24. This variant of the round-to-nearest method is also called unbiased rounding, convergent rounding, statistician's rounding, Dutch rounding, Gaussian rounding, or bankers' rounding. For most reasonable distributions of y values, the expected (average) value of the rounded numbers is essentially the same as that of the original numbers, even if the latter are all positive (or all negative). This is widely used in bookkeeping.


Так что никакого глюка. В Help именно так и описано поведение Round.

Это сообщение отредактировал(а) Демо - 10.12.2009, 11:44


--------------------
    
PM MAIL ICQ Skype   Вверх
amsoft
Дата 10.12.2009, 11:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 201
Регистрация: 17.10.2009
Где: KZ, Astana

Репутация: 3
Всего: 4



Демо
я знаю - читал уже, но меня не устраивает такой метод округления.
Кстати, раз уж его называют "Banker’s Rounding", то могли бы его засунуть в функцию типа BankerRound, а Round сделали бы нормальным.

Чуть модернизировал, теперь работает с отрицательными числами тоже  smile 

Код

function SmartRound(X: Extended): Int64;
begin
Result := Trunc(X);
if Abs(X - Result) >= 0.5
then if X < 0
     then Dec(Result)
     else Inc(Result);
end;


ЗЫ Не побоюсь этого слова Smart  smile 
--------------------
"Кто бы ты ни был - не думай о себе слишком"Дельфин
PM   Вверх
amsoft
Дата 10.12.2009, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 201
Регистрация: 17.10.2009
Где: KZ, Astana

Репутация: 3
Всего: 4



кстати, есть ли в делфях уже готовая подобная функция, чтобы велосипедостроительством не заниматься?
--------------------
"Кто бы ты ни был - не думай о себе слишком"Дельфин
PM   Вверх
profesiachuvak
Дата 10.12.2009, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 283
Регистрация: 7.11.2009
Где: Беларусь, Минск

Репутация: нет
Всего: 4



Цитата(amsoft @ 10.12.2009,  12:53)
кстати, есть ли в делфях уже готовая подобная функция, чтобы велосипедостроительством не заниматься?

Да какой тут велосипед, ранее предлогалось сделать так
Код

var 
i,s:real;
begin
i:=2.5; /к примеру возьмём это число
s:=trunc(i+0.5);
end;


Вот и весь велосипед. Округляй с помощью trunc() и получишь нормальное математическое округление по школьным правилам.


--------------------
Закон Мерфи :если есть вероятность того, что какая-нибудь неприятность может случиться, то она обязательно произойдет.
PM MAIL   Вверх
amsoft
Дата 10.12.2009, 15:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 201
Регистрация: 17.10.2009
Где: KZ, Astana

Репутация: 3
Всего: 4



profesiachuvak

где-то в этой теме промелькала такая мысль, почему-то не обратил на нее внимание сразу

Thx
--------------------
"Кто бы ты ни был - не думай о себе слишком"Дельфин
PM   Вверх
Alexeis
Дата 10.12.2009, 15:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



profesiachuvak, а если число отрицательное? 



--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Демо
Дата 10.12.2009, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 3.11.2005

Репутация: 30
Всего: 50



Цитата(profesiachuvak @  10.12.2009,  13:43 Найти цитируемый пост)
Вот и весь велосипед. Округляй с помощью trunc() и получишь нормальное математическое округление по школьным правилам.


Этот велосипед для простейших случаев.


Цитата(profesiachuvak @  10.12.2009,  13:43 Найти цитируемый пост)
var i,s:real;begini:=2.5; /к примеру возьмём это числоs:=trunc(i+0.5);end;


Простой пример - 2.4(9), получающееся в процессе вычислений.


--------------------
    
PM MAIL ICQ Skype   Вверх
Beltar
Дата 10.12.2009, 18:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 3
Всего: 7



Цитата

Округляй с помощью trunc() и получишь нормальное математическое округление по школьным правилам.


trunc(3.9)=3, а не 4.

Лучше уж frac(x)>0.5 проверять.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
amsoft
Дата 10.12.2009, 18:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 201
Регистрация: 17.10.2009
Где: KZ, Astana

Репутация: 3
Всего: 4



Alexeis
немного подшаманить можно:

Код

if i < 0 
then Result := Trunc(i-0.5) 
else Result := Trunc(i+0.5)


Добавлено через 1 минуту и 2 секунды
Beltar
а прибавлять 0.5 кто будет?
--------------------
"Кто бы ты ни был - не думай о себе слишком"Дельфин
PM   Вверх
~FoX~
Дата 10.12.2009, 18:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЕ рыжий!!!
****


Профиль
Группа: Участник Клуба
Сообщений: 2819
Регистрация: 8.10.2003
Где: Зеленоград

Репутация: 13
Всего: 68



Poseidon, Лениво читать весь тред, но имел счастья сталкнутся с обратной проблемой, вобшим не суть дело... Тип Currency даст тебе то что ты хочешь поиметь... 

Это сообщение отредактировал(а) ~FoX~ - 10.12.2009, 18:34


--------------------
user posted image
…множественность никогда не следует полагать без необходимости…
PM MAIL WWW ICQ Jabber   Вверх
Beltar
Дата 10.12.2009, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 3
Всего: 7



Чего прибавлять??

Код

function TheOnlyTrueRound(X:Extended):Integer;
begin
if frac(X)>=0.5 then {0.5 в двоичной вроде 0.1, конечная дробь} Result:=trunc(X)+1
  else Result:=trunc(X)-1;
end


Или я не прав:


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
Alexeis
Дата 10.12.2009, 18:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(amsoft @  10.12.2009,  17:30 Найти цитируемый пост)
немного подшаманить можно:

  Можно, но тут уже добавилось ветвление и конструкция перестала быть изящной.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
amsoft
Дата 10.12.2009, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 201
Регистрация: 17.10.2009
Где: KZ, Astana

Репутация: 3
Всего: 4



Alexeis, ИМХО Без ветвления никуда  smile

Добавлено через 1 минуту и 17 секунд
Beltar, главное результат

ЗЫ мой прошлый велосипед с десятью колесами и двумя сиденьями в топку  smile 
--------------------
"Кто бы ты ни был - не думай о себе слишком"Дельфин
PM   Вверх
bems
Дата 10.12.2009, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Модератор: amsoft, не нужно откапывать старые темы.






--------------------
Обижено школьников: 8
PM MAIL   Вверх
amsoft
Дата 11.12.2009, 07:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 201
Регистрация: 17.10.2009
Где: KZ, Astana

Репутация: 3
Всего: 4



bems
я вообще хотел создать новую тему, но нашел тему с похожей проблемой и решил "добить" ее до конца, ибо это меня тоже касается.

В принципе с этим вопросом разобрались.
Тема может быть закрыта.
--------------------
"Кто бы ты ни был - не думай о себе слишком"Дельфин
PM   Вверх
Beltar
Дата 11.12.2009, 08:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 3
Всего: 7



Что-то я туплю.

Код

function TheOnlyTrueRound(X:Extended):Integer;
begin
Result:=trunc(X)+Integer(frac(X)>=0.5);
end



--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
bems
Дата 11.12.2009, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



amsoft, ну это так, на будущее. Если бы я увидел в этом нарушение, было бы предупреждение в личное дело. В данном случае поднятие топика оправдано, да.


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1935 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.