Trunc + приведение типов..
От: Аноним  
Дата: 13.11.06 12:37
Оценка:
Есть такой код:

const
  Cnt: double = 7.26;
var
  a: longword;
begin
  a:=Trunc(133584);
  ShowMessage(IntToHex(a,8));

  a:=Trunc(18400 * Cnt);
  ShowMessage(IntToHex(a,8));
end;


Для справки: 18400 * 7.26 = 133584

Т.е. по идее оба сообщения должны совпадать.. Тем не менее первое выдаёт 209D0, а второе 209CF.

Что это и как лечится?
Re: Trunc + приведение типов..
От: kochmin_alexandr Россия  
Дата: 13.11.06 12:43
Оценка:
А> Что это и как лечится?

это ошибка округления float типов при двочном представлении.

--
Кочмин Александр
Posted via RSDN NNTP Server 2.0
Re[2]: Trunc + приведение типов..
От: Danchik Украина  
Дата: 13.11.06 12:52
Оценка:
Здравствуйте, kochmin_alexandr, Вы писали:

А>> Что это и как лечится?


_>это ошибка округления float типов при двочном представлении.


Как вариант лечения округлите, например, до двух знаков после запятой:
a := Round (18400 * Cnt * 100) div 100
Re[3]: Trunc + приведение типов..
От: Аноним  
Дата: 13.11.06 13:12
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Как вариант лечения округлите, например, до двух знаков после запятой:

D>
D>a := Round (18400 * Cnt * 100) div 100
D>


Ok, а есть вариант заставить работать первый вариант
a:=Trunc(133584);

_НЕ_ правильно? Как в случае с глюком. Не спрашивайте почему, объяснять долго..
Re[4]: Trunc + приведение типов..
От: Danchik Украина  
Дата: 13.11.06 13:31
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Danchik, Вы писали:


D>>Как вариант лечения округлите, например, до двух знаков после запятой:

D>>
D>>a := Round (18400 * Cnt * 100) div 100
D>>


А> Ok, а есть вариант заставить работать первый вариант

А>
А>a:=Trunc(133584);
А>

А>_НЕ_ правильно? Как в случае с глюком. Не спрашивайте почему, объяснять долго..

А что мешает написать свой Trunc ?
Re[4]: Trunc + приведение типов..
От: Shurik Ilyin Россия http://ppi-esa.narod.ru
Дата: 13.11.06 13:44
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Danchik, Вы писали:


D>>Как вариант лечения округлите, например, до двух знаков после запятой:

D>>
D>>a := Round (18400 * Cnt * 100) div 100
D>>

Можно попробовать через задницу:
a:=Trunc(StrToFloat(FloatToStr(18400 * Cnt)));


А> Ok, а есть вариант заставить работать первый вариант

А>
А>a:=Trunc(133584);
А>

А>_НЕ_ правильно? Как в случае с глюком. Не спрашивайте почему, объяснять долго..
Re[3]: Trunc + приведение типов..
От: Аноним  
Дата: 13.11.06 13:59
Оценка:
Здравствуйте, Danchik, Вы писали:

_>>это ошибка округления float типов при двочном представлении.


Щас экспериментировал.. Возник еще вопрос — почему эта ошибка пропадает
при переносе кода в .dll?
Re[4]: Trunc + приведение типов..
От: kochmin_alexandr Россия  
Дата: 13.11.06 14:19
Оценка:
А> Здравствуйте, Danchik, Вы писали:
А>
А> _>>это ошибка округления float типов при двочном представлении.
А>
А> Щас экспериментировал.. Возник еще вопрос — почему эта ошибка
А> пропадает
А> при переносе кода в .dll?

чудес не бывает

--
Кочмин Александр
Posted via RSDN NNTP Server 2.0
Re[5]: Trunc + приведение типов..
От: Аноним  
Дата: 13.11.06 15:47
Оценка:
Здравствуйте, kochmin_alexandr, Вы писали:

_>чудес не бывает


Да, я тоже так считаю.. но!

Вставляем в .dll:

const
  Const5: double = 7.26;
...
  OutputDebugString(PChar('+++TEST:'+IntToHex(Trunc(18400 * Const5),8)));


Выдаёт 209D0

Создаём новый проект, вставляем в OnButton:

const
  Const5: double = 7.26;
begin
  ShowMessage('+++TEST:'+IntToHex(Trunc(18400 * Const5),8));


Выдаёт 209CF

Где правда??
Re[6]: Trunc + приведение типов..
От: kochmin_alexandr Россия  
Дата: 14.11.06 03:47
Оценка:
А> Где правда??

посмотри ассемблерный код и сравни.

--
Кочмин Александр
Posted via RSDN NNTP Server 2.0
Re[7]: Trunc + приведение типов..
От: Аноним  
Дата: 14.11.06 07:40
Оценка:
Здравствуйте, kochmin_alexandr, Вы писали:

_>посмотри ассемблерный код и сравни.


Да, в итоге так и пришлось сделать.. Нашёл проблему! При компиляции dll управляющий код сопроцессора выставлялся в $1232, что заставляет его работать в режиме максимальной точности! По умолчанию этот код равен $1332 (пониженной точности) и выставляется в модуле system

  Default8087CW: Word = $1332;{ Default 8087 control word.  FPU control
                                register is set to this value.
                                CAUTION:  Setting this to an invalid value
                                          could cause unpredictable behavior. }


Для изменения управляющего кода используется следующая инструкция (delphi)

  Set8087CW($1332);


Почитать на эту тему можно здесь: здесь
Re[8]: Trunc + приведение типов..
От: kochmin_alexandr Россия  
Дата: 14.11.06 07:53
Оценка:
А> Для изменения управляющего кода используется следующая инструкция
А> (delphi)
А>
А>
 А>   Set8087CW($1332);
 А>


ну вот видишь как все круто



--
Кочмин Александр
Posted via RSDN NNTP Server 2.0
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.