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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ошибка при округлении 
:(
    Опции темы
xkor
Дата 17.12.2009, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Доброго времени суток.
Столкнулся с абсолютно непонятной мне проблемой при работе с вещественными числами.
Моя программа принимает координаты различных объектов в виде 3х чисел типа Single (в программе уже хранятся в типе Double), далее необходимо их округлить с заданной точностью (6 знаков после запятой) и записать в файл, но вот при округлении изредка происходит какая то не объяснимая вещь, при абсолютно нормальных числах (например 583.23472547134) функция RoundTo из модуля Math вываливается с сообщением "Invalid floating point operation".
Судя по дебагеру вываливается при вызове внутри неё Round на одной из ассемблерных команд:
        FISTP  qword ptr [ESP]
        FWAIT

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

В общем может кто знает что происходит и как сделать чтобы работало без сбоев?
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
RomanEEP
Дата 18.12.2009, 07:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Используешь OpenGL или какие либо другие библиотеки, которые вызывают функцию Set8087CW()? Какая версия Delphi?
PM MAIL   Вверх
xkor
Дата 18.12.2009, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



RomanEEP, нет, приложение довольно простенькое, одно окошко, кнопка и ещё пара стандартны контролов, принимает данные по WM_CopyData от другого приложения, отсеивает нужные и сохраняет в файл в виде JSON строки, с вещественными числами работает только в одном месте где просто их округляет. Дельфя 2007я.
ЗЫ программа шифруется с помощью VMProtect, но не думаю что он использует Set8087CW.

Я тут подумал может вызов SetPrecisionMode(pmDouble) перед округлением поможет, вдруг и правда Set8087CW где то вызывается, правда помогло ли узнаю не скоро, редко эта ошибка вылазит.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Bitter
Дата 18.12.2009, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный лентяй
***


Профиль
Группа: Завсегдатай
Сообщений: 1209
Регистрация: 15.8.2004
Где: Харьков, Ukraine

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



Возхможно дело не в функции округления, бывает такое, что ошибка вылазит даже на более простых операциях типа X := 0; Возможно, что где-то у тебя происходит либо выход за пределы массива или RangeCheck Error, или еще что-то связанное с "неправильным" доступом к памяти. Тогда это проявляется в виде таких вот invalid floating в других частях программы. Почему так происходит не могу точно объяснить, но у меня такое иногда бывает.
PM MAIL ICQ Skype   Вверх
RomanEEP
Дата 18.12.2009, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



В общем причина проблемы видимо следующая: в сопроцессоре есть набор флагов управляющие вызовом/не вызовом исключительных ситуации. Их состояние можно посмотреть в отладчике View->Debug Windows->FPU
Знаит они следующее:
0 -> IM  Invalid Operation
1 -> DM  Denormalized Operand
2 -> ZM  Zero Divide
3 -> OM  Overflow
4 -> UM  Underflow
5 -> PM  Precision
Если флаг взведен, значит исключение маскируется, т.е. не вызывается.
Можно поделить на ноль и никакой ошибки не выскочит.
Чудеса появляются тогда, когда какая-нибудь процедура пытается поменять состояние этих флагов. Она(процедура) может поменять состояние этих флагов командой fldcw, и программа будет нормально работать. НО: вызов любой команды сопроцессора, после того как исключения были размаскированы приведет к появлению ошибки, кот произошла последней на тот момент, когда исключения были замаскированы!

Я думаю надо просто посмотреть при старте программы не замаскированы ли в программе исключения. И поискать места их возможной установки. Особенно распостраненны такие места в разных функциях округления. Такой косяк был в системных функциях в Delphi 5 и был поправлен в семерке. Может в 2007 его внесли снова)))
PM MAIL   Вверх
RomanEEP
Дата 15.1.2010, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



В 2010 Delphi баг всё таки внесли. 
http://qc.embarcadero.com/wc/qcmain.aspx?d=81203
PM MAIL   Вверх
Staruha
Дата 17.1.2010, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



У меня такая ошибка выскакивала.Проблема точка или запятая


--------------------
Возмездие настигнет
PM MAIL   Вверх
profesiachuvak
Дата 17.1.2010, 19:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Похоже нужно так: 

583,23472547134 

На разных машинах которых я работал, требовалась то точка, то запятая. Похоже в этом ошибка.

Добавлено через 1 минуту и 47 секунд
Цитата(Staruha @  17.1.2010,  18:50 Найти цитируемый пост)
У меня такая ошибка выскакивала.Проблема точка или запятая 


Точно!Не заметил.

Это сообщение отредактировал(а) profesiachuvak - 17.1.2010, 19:44


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


Эксперт
***


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

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



Добавь на вкладку Project

между begin и end

  
Код

DecimalSeparator:=',';



--------------------
Возмездие настигнет
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

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

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

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

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


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

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


 




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


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

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