lazarus и WinCE , проблема с отображением float типов

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

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

lazarus и WinCE , проблема с отображением float типов

Сообщение votan » 31.01.2012 10:43:04

Здравствуйте.
Может кто знает, в чем глюк.
При использование функции floattostr для типов double,extended,real и вывод их на контролы(например в label1.caption:=floattostr(x);) производиться какаето странная конвертация исходного числа, причем для типа currency все нормально.

например
Код: Выделить всё
var x:double;
x1:currency;
begin
x  :=9109.453823;
x1:=9109.453823;
label1.caption:=floattostr(x); //выводит  9119.5549230
label2.caption:=floattostr(x1); //выводит 9109.453823;
x1:=x;
label2.caption:=floattostr(x1); //выводит  9109.453823;--т.е. значение имеено в переменной(x) правильные
//далее ... тоже интересно
FloatSpinEdit1.value:=x; //выводит  9119.5549230
FloatSpinEdit2.value:=x1; //выводит  9119.5549230
FloatSpinEdit2.value:=FloatSpinEdit1.value;//выводит 9130,65590---хотя по сути должно быть на 100 процентов 9119.5549230


если присмотреться к этим преобразованием(много цифирь просматривал), то видно что происходит округление каждой цифры в данном числе и если больше 5 прибавляет 1 к высшему разряду.


PS под WinXp данный пример отрабатывается нормально.
под wince + arm , ситуация как я выше изложил.
votan
незнакомец
 
Сообщения: 1
Зарегистрирован: 31.01.2012 09:51:17

Re: lazarus и WinCE , проблема с отображением float типов

Сообщение suharew » 11.07.2013 23:57:32

Добрый день. Поддерживаю вопрос. У меня такая же ситуация. Lazarus 1.0 FPc 2.6.0
Конечно, я не проверял работу на более новом, "кандидатском" компиляторе, но FPC 2.6.0 под winCE не умеет работать с FloatToStr! Т.е. преобразование проходит, но если встречается цифра больше 5 то старший разряд увеличивается на единицу. Другими словами, FloatToStr (26.06428) выдаст 36.16438!

Кто знает как решить данную проблему. Не работает именно под WinCE
suharew
незнакомец
 
Сообщения: 2
Зарегистрирован: 26.01.2013 13:19:30

Re: lazarus и WinCE , проблема с отображением float типов

Сообщение Сквозняк » 13.07.2013 00:41:52

Кто знает как решить данную проблему. Не работает именно под WinCE


Если в WinCE Str работает также как в линуксе и ХРюше, то вместо FloatToStr использовать другую функцию.
Код: Выделить всё
FUNCTION F_STR_V(Q1: EXTENDED):STRING;
VAR
Q64: INT64;
S5: STRING;
Q3: BYTE;
BEGIN
F_STR_V:='';
IF Q1<0 THEN BEGIN 
             F_STR_V:='-';
             Q1:=ABS(Q1);
             END;
Q64:=TRUNC(Q1);
STR(Q64,S5);
F_STR_V:=F_STR_V+S5;
Q1:=FRAC(Q1)+1;
STR(Q1,S5);
FOR Q3:=1 TO 17 DO S5[Q3]:=S5[Q3+3];
SETLENGTH(S5,16);
IF S5='0000000000000000' THEN S5:='00';
F_STR_V:=F_STR_V+'.'+S5;
END;
Сквозняк
энтузиаст
 
Сообщения: 1129
Зарегистрирован: 29.06.2006 22:08:32

Re: lazarus и WinCE , проблема с отображением float типов

Сообщение rxt » 19.07.2013 17:36:43

Типы данных:
Real – стандартный тип Паскаля. Когда создавался Паскаль, процессоры ещё не имели встроенной поддержки работы с вещественными числами.
Extended, Double, Single – введены Borland в Turbo Pascal для поддержки сопроцессорных типов. При чём, Extended – это родной для сопроцессора тип, а Double, Single получаются из него простым усечением и не совпадают с Real, операции с ними значительно быстрее последнего.

Округление:
Стандарт IEEE-754 описывает несколько способов округления вещественных чисел. Так случилось, что разработка стандарта и разработка сопроцессора компанией Intel совпали. Intel открыл некоторые спецификации своей разработки, которые и легли в основу стандарта. Один из способов округления носит название «банковское округление» или «бухгалтерское округление», который предписывает округлять в сторону ближайшего целого чётного числа. Это округление используется компанией Intel по умолчанию.
Простыми словами банковское округление выглядит: если цифра перед пятёркой чётная, то округление вниз, иначе вверх.

Сопроцессор:
Для управления сопроцессором служат управляемые регистры и команды. В Delphi и FPC эти команды завёрнуты в вызовы функций: Set8087CW, Get8087CW, Default8087CW. Принимая соответствующие параметры команд, позволяют управлять точностью, округлением и др..
К примеру Set8087CW(Get8087CW and $FCFF or $0200) - переведёт сопроцессор в режим 53-разрядной точности представления мантиссы(дробной части), а Set8087CW(Get8087CW and $FCFF) - в режим 24-разрядной точности.

У прикладного программиста редко появляется нужда в низкоуровневых вызовах. В модуле Math, есть функции, с помощью которых легко управлять поведением сопроцессора. Одной из таких, является функция SetRoundMode(её пара GetRoundMode), которая управляет округлением, принимая и возвращая один из параметров:
  • rmNearest — округление к ближайшему чётному (по умолчанию)
  • rmDown — округление вниз
  • rmUp — округление вверх
  • rmTruncate — отбрасывание дробной части
Код: Выделить всё
var
  rm: TFPURoundingMode;
Begin
  rm   := SetRoundMode(rmUp); // режим округления вверх , функция возвращает предыдущее значение.
  // a := Round(b)
  // или другие Ваши действия
  SetRoundMode(rm) // обязательно! восстановим  сохранённое значение
end;



Особенность WinCE:
За работу с вещественными числами в WinCE отвечает библиотека fpcrt.dll. Её функции импортируются coredll.dll. И вся забава в том, что по умолчанию fpcrt.dll лишь эмулирует работу с сопроцессором, выполняя все операции в целочисленном блоке. Отсюда потеря скорости и расхождение результатов. Вы можете переписать и заменить библиотеку fpcrt.dll своей реализацией. О том, как это сделать подробно рассказывает ОРАКУЛ. Это для WinCE 6.
А вот Windows Embedded Compact 7 ведёт себя уже по-другому: fpcrt.dll динамически определяет операции с вещественными числами и решает, как ей использовать аппаратные средства. Об этом также спрашивать у ОРАКУЛА.
В сети можно найти исходники и откомпилированные модули, также исходники выкладывались на сайте http://arm.com/.

Danger!
Раз уж коснулись сопроцессора, замечу:
На конференциях Borland активно обсуждались и обсуждаются вопросы, связанные с операциями вещественных чисел. В одном из таких вопросов говорилось, что по неизвестным причинам при работе с вещественными числами программы падали или давали непредсказуемый результат. Оказалось, что при вызове некоторых API функций менялось управляющее слово в сопроцессоре, а после работы прежнее значение не восстанавливалось. Ну забыл кто-то восстановить.. бывает))). Вскоре виновник был найден и уже начиная с версии Delphi 7, а также во всех последующих версиях включая текущую(Delphi XE4), в модуле Windows.pas встречается такой код:

Код: Выделить всё
function CreateWindowEx(dwExStyle: DWORD; lpClassName: PChar;
  lpWindowName: PChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer;
  hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND;
var
  FPUCW: Word;
begin
  FPUCW := Get8087CW;
  Result := _CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle,
    X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
  Set8087CW(FPUCW);
end;

Ошибка замечалась на более ранних версиях Windows (Win98, Win95), но также были слухи о её появлении и в версиях Win NT после доустановки каких-либо программ. Если Вы посмотрите на аналогичный модуль из библиотеки fpc(в данный момент речь идет о версии 2.6.2) Вы ничего подобного там не найдёте. А вот заглянув в модуль sysutils.pp, можно увидеть следующее:

Код: Выделить всё
Procedure InitInternational;
var
  { A call to GetSystemMetrics changes the value of the 8087 Control Word on
    Pentium4 with WinXP SP2 }
  old8087CW: word;
begin
  /// workaround for Windows 7 bug, see bug report #18574
  old8087CW:=Get8087CW;
  SysLocale.MBCS:=GetSystemMetrics(SM_DBCSENABLED)<>0;
  { ** SKIPPED ** }
  Set8087CW(old8087CW);
end;

Видно, что кто-то из разработчиков fpc всё же столкнулся с ошибкой и обезопасил только себя.
  • Почему, зная о проблеме, не завернут сам вызов GetSystemMetrics подобно тому, как это сделали ребята из Borland?!
  • Это уверенность в том, что никто не использует вызов GetSystemMetrics?
  • ... ?

Для более подробного изучения работы с вещественными числами настоятельно рекомендую обратиться к статьям:
Неочевидные особенности вещественных чисел © Антон Григорьев,
Загадки округления © Алексей Михайличенко.
Обязательно загляните в разделы «обсуждение» статей, где можно найти ответы на возникающие вопросы.
rxt
новенький
 
Сообщения: 15
Зарегистрирован: 03.03.2013 13:54:02


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

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

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

Рейтинг@Mail.ru