Просьба проверить.

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Просьба проверить.

Сообщение WAYFARER » 19.02.2011 22:05:04

Толи лыжи не едут, толи еще что?


Код: Выделить всё
var
i, ii: Real;
b: integer;
begin
i := Frac(X)*100;
ii := Frac(i);


x=0.065 - ii=0.5 - Верный результат
x=11.085 - ii=0.5..7 - Верный результат
x=11.065 - ii=0.4999999999 (и так если во 2-ом символе от запятой число от 3 до 8 )
x=1.065 - ii=0.49999999999 и т.д. и т.п.

Ткните носом пожалуйста!

Добавлено спустя 34 минуты 30 секунд:
Если использовать тип Extended то кол-во ошибок сокращается, но погрешности все равно есть...
Последний раз редактировалось WAYFARER 20.02.2011 00:21:28, всего редактировалось 1 раз.
Аватара пользователя
WAYFARER
энтузиаст
 
Сообщения: 537
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: Просьба проверить.

Сообщение Ism » 20.02.2011 00:09:28

что это за адские вычисления, что вы вычисляете ? Через несколько последовательных преобразований ошибка будет накапливаться . И повышение разрядности переменной тут не спасет

Добавлено спустя 9 минут 44 секунды:
возможно, ошибка в логике вычисления
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Просьба проверить.

Сообщение WAYFARER » 20.02.2011 00:26:13

Пост поправил, лишнее убрал, дабы понятней было. :)
Ism писал(а):что это за адские вычисления, что вы вычисляете

И нет там адских вычислений, обычное бухгалтерское (банковское) округление(если цифра перед пятеркой - четная, то округление вниз, иначе вверх )

Добавлено спустя 5 минут 43 секунды:
Мне собственно и хотелось бы выяснить причину погрешности.
Аватара пользователя
WAYFARER
энтузиаст
 
Сообщения: 537
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: Просьба проверить.

Сообщение Padre_Mortius » 20.02.2011 00:38:19

попробуйте использовать ValReal

Добавлено спустя 1 минуту 32 секунды:
А вообще вот решение
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Re: Просьба проверить.

Сообщение Ism » 20.02.2011 00:42:07

может использовать функцию

http://4programmers.org.ua/programming/ ... posle.html

Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
  i,ii:real;
begin
  i := Frac(11.065)*100;
  ii := Frac(i);
  Edit1.Text:=FloatToStr(ii);
end;       


результат 0.5
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Просьба проверить.

Сообщение Padre_Mortius » 20.02.2011 00:46:17

под 32-х битной виндой может и так, а под 64-х битным линуксом или виндой результат будет другой. Это обусловлено работой функции Frac
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Re: Просьба проверить.

Сообщение Ism » 20.02.2011 00:52:38

Что именно с frac ? Вообщето функции должны везде работать одинаково.
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Просьба проверить.

Сообщение WAYFARER » 20.02.2011 01:02:01

Padre_Mortius писал(а):А вообще вот решение

К сожалению нет там решения:( Этого идиотизма в нужном виде нигде нет.
Padre_Mortius писал(а):попробуйте использовать ValReal

Гениально! Огромнейшее спасибо!
Но все таки интересно почему так происходит?

Ism писал(а):procedure TForm1.Button1Click(Sender: TObject);
var
  i,ii:real;
begin
  i := Frac(11.065)*100;
  ii := Frac(i);
  Edit1.Text:=FloatToStr(ii);
end;       


а попробовать поиграться с числами? 1111.065 у меня дает результат 0,49...
Аватара пользователя
WAYFARER
энтузиаст
 
Сообщения: 537
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: Просьба проверить.

Сообщение Padre_Mortius » 20.02.2011 01:11:00

Но все таки интересно почему так происходит?

В самой функции Frac входящее значение и результат объявлены как тип ValReal, который в свою очередь платформозависимый и описан в файле systemh.inc
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Re: Просьба проверить.

Сообщение Ism » 20.02.2011 01:25:28

Да , ошибка имеет место, есть подозрение на глюк. Может прокатит i-trunc(i)

Хотя нет, и здесь ошибка в 10 м знаке. У меня подозрение, что вычисления правильные, а виновата функция FloatToStr она некорректно выводит результат.

Кстати есть еще функция FloatToStrF более умная. http://www.delphisources.ru/pages/faq/f ... F.php.html

Попробуйте положить результат i := Frac(11.065)*100; прямо в какую нибудь базу данных , если есть возможность (это один из па танца с бубном :))

как вариант можно работать с числами как со строками где возможно (например отделять дробную и целую часть)

Добавлено спустя 7 минут 51 секунду:
у меня 32 битная система
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Просьба проверить.

Сообщение WAYFARER » 20.02.2011 01:36:28

В общем, по поводу банковского округления, гуглил, и кроме вопроса "как реализовать" от множества людей ничего не нагуглил.

может пригодится кому

Арифметическое округления:
Код: Выделить всё
function aRound(X: ValReal; Precision: Integer): ValReal; 
var
i, ii : ValReal;
begin
i := Frac(X)*Precision;
ii := Frac(i);
i := Int(i);
if ii >=  0.5 then i := i + 1;
if ii <= -0.5 then i := i - 1;
aRound := Int(X) + i/Precision;
end;


Банковское округление:
Код: Выделить всё
function bRound(X: ValReal): ValReal;   
var
   i, ii: ValReal;
   b: integer;
begin
i := Frac(X)*100;
ii := Frac(i);
i := Int(i);
if (ii >=0.5) and (ii < 0.6) then
begin
  b:=StrToInt(Copy(floatToStr(frac(x)),4, 1));
  if (b and 1) = 0  then i := i  else i := i + 1 ;
Result := Int(X) + i/100;
end else
begin
  Result := around(x,100);
end;                             
end;   

Если кто то решит поправить буду только рад.


Интересная статья "Загадки округления"
Если бы бухгалтер был магом и чародеем, он несомненно решил бы проблему так, чтобы какой-нибудь саблезубый тигр откусил руку, или хотя бы нечетное количество пальцев нашему волосатому пращуру, придумавшему десятичную систему счисления, чтобы в ней не осталось "середины". Но он выкрутился хитрее - половину отбрасываемых пятерок стал округлять вверх, а половину - вниз. Чтобы его не обвинили в личных пристрастиях, критерием стала цифра перед пятеркой - если она четная, то округление вниз, иначе вверх. Это правило и называется правилом "Бухгалтерского" (или "Банковского") округления.


Добавлено спустя 2 минуты 29 секунд:
Ism
Спасибо! Завтра буду ломать голову дальше в чем именно причина.
Ism писал(а):у меня 32 битная система

У меня тоже, завтра еще если времени хватит попробую на других платформах.
Последний раз редактировалось WAYFARER 25.04.2015 00:55:30, всего редактировалось 1 раз.
Аватара пользователя
WAYFARER
энтузиаст
 
Сообщения: 537
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: Просьба проверить.

Сообщение Иван Шихалев » 20.02.2011 02:45:15

А зачем банковское округление реализовывать на плавающей точке? Есть же тип Currency.
Аватара пользователя
Иван Шихалев
энтузиаст
 
Сообщения: 1138
Зарегистрирован: 15.05.2006 11:26:13
Откуда: Екатеринбург

Re: Просьба проверить.

Сообщение WAYFARER » 20.02.2011 03:26:59

Иван Шихалев писал(а):Есть же тип Currency.

А как это сделать? Я с Currency не работал никогда.
Аватара пользователя
WAYFARER
энтузиаст
 
Сообщения: 537
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: Просьба проверить.

Сообщение Vadim » 20.02.2011 07:32:06

WAYFARER
Currency - это почти целое число, но с четырмя знаками после запятой. Там округление (если цифр после запятой больше 4-ёх получается) происходит автоматом по бухгалтерскому принципу.
Работать так же, как и с другими простыми типами.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

Рейтинг@Mail.ru