Ошибка invalid floating point operation как исправить

При подключении к «1C: Предприятие 8.3» в узле импорта и/или в мастере подключений возникает ошибка «Invalid floating point operation». Что делать?

Рисунок 1 – Ошибка «Invalid floating point operation»

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

В случае если сценарий импорта из 1С выполняется интерактивно в интерфейсе DStudio, решение для данной ошибки следующее:

  1. Открыть в текстовом редакторе файл сценария (расширение «ded»);
  2. Найти раздел «EnvironmentVariables» и в описании переменной «DisableFloatExceptions» добавить строку <Value>1</Value>:
    
    ...    
        <EnvironmentVariables>
           <Version>1</Version>
            <Vars>
                <Count>2</Count>
                <I_0>
                    <Name>LocaleID</Name>
                    <DataType>dtInteger</DataType>
                    <Value>1049</Value>
                </I_0>
               <I_1>
                   <Name>DisableFloatExceptions</Name>
                    <DataType>dtBoolean</DataType>
                    <Value>1</Value>              \Эта строка добавляется!
                </I_1>
            </Vars>
        </EnvironmentVariables>
    ...
    
    
  3. Сохранить файл сценария.

Значение переменной «DisableFloatExceptions» при правильной правке сценария отразится в настройках Deductor (Рис. 2)

Рисунок 2 – Отображение изменений в настройках

Важно: При изменении и последующем сохранении сценария в DStudio данные изменения могут быть утеряны.

В случае если сценарий используется в пакетном режиме, решение следующее:

Необходимо использовать управляющий сценарий, в котором при помощи узла «Команда ОС» запускать на выполнение DStudio.exe с параметрами запуска сценария импорта из 1С. При этом сам сценарий импорта из 1С править вышеописанным способом не надо, значение переменной DisableFloatExceptions можно передавать в параметрах запуска сценария. В узле «Команда ОС» строка запуска будет примерно такой:


chcp 1251
"C:Program Files (x86)BaseGroupDeductorBinDStudio.exe" "C:ПутьКФайлу1c.ded" /DisableFloatExceptions=True /RUN /LOG /LOGFILE="C:ПутьКФайлуlog.log" /LOGMODE

Важно: Необходимо обратить внимание, что при изменении значения переменной DisableFloatExceptions результат работы узла Калькулятор может поменяться, а именно меняется результат обработки значения NULL.
Пример: при DisableFloatExceptions = True значение выражения Round(Null()) > 1 возвращает False. При DisableFloatExceptions = False это выражение возвращает Null.
В связи с этим, при применении данного решения необходимо проверить работу сценария.

The Problem

The issue is that your variable fat1 is getting too big and overflowing. With free pascal, your code causes a 205 error (Floating point overflow). This is similar to a 207 Invalid floating point operation — free pascal run-time error codes. The real types that are relevant to your code have the following constraints (from the free pascal data types wiki page):

Type       Range                   Significant digits   Bytes
Real       platform dependent      ???                  4 or 8
Single     1.5E-45 .. 3.4E38       7-8                  4
Double     5.0E-324 .. 1.7E308     15-16                8
Extended   1.9E-4932 .. 1.1E4932   19-20                10

The Work Around

You simply need to account for the possibility of overflow with your largest variable. It is not possible to simply check if the variable is above it’s max value so you should do the reverse of the operation that could cause the overflow. I also used Extended to have a better estimate.

var max_fat : Extended = 1.1 * power(10,4932);
var should_step : Extended= max_fat / (cont1) / (cont1-1) / (cont1-2) / (cont1-3);

then in your while loop include the check:

fat1 < should_step

The result of this reverse operation is the maximum that the variable fat1 can be before it overflows. I use the Math library to help calculate the maximum Extended. The following test code works for me:

program cosseno;

Uses Math;

var fat1, fat2, n1, n2, cont1, cont2, s, max_fat, should_step : Extended;
   begin
      s := 0.5;
      fat1 := 24;
      fat2 := 720;
      n1 := 1/fat1;
      n2 := 1/fat2;
      cont1 := 8;
      cont2 := 10;

      max_fat := 1.1 * power(10,4932);

      should_step := max_fat;

      while ((n1 - n2) > 0.000001) AND (fat1 < should_step) do
       begin
          should_step := max_fat / (cont1) / (cont1-1) / (cont1-2) / (cont1-3);

          fat1 := (cont1) * (cont1-1) * (cont1-2) * (cont1-3) * fat1;
          fat2 := (cont2) * (cont2-1) * (cont2-2) * (cont2-3) * fat2;
          cont1 := cont1 + 4;
          cont2 := cont2 + 4;
          n1 := n1 + 1/fat1;
          n2 := n2 + 1/fat2;
          writeln('fat1  > ', fat1);
          writeln('fat2  > ', fat2);
          writeln('cont1 > ', cont1);
          writeln('cont2 > ', cont2);
          writeln('n1    > ', n1);
          writeln('n2    > ', n2);
       end;

      s := s + n1 - n2;
      writeln('<==================>');
      writeln(s);
   end.

The code yields the following result:

5.40302305868139717414E-0001

which I checked to be correct for at least the first 10 digits.

Цитата
Сообщение от Puporev
Посмотреть сообщение

Код Delphi
1
2
b1:=Sqrt(DfX1); нахожу квадратный корень
b2:=Sqrt(DfX2);

Здесь при определенных значениях х, под корнем получается отрицательное число.
Если числа вводятся безконтрольно, то в этом случае можно выдавать предупреждение
Код Delphi
1
2
if DfX1<0 then showmessage(‘Подкоренное выражение меньше ноля’) else b1:=Sqrt(DfX1);

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

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
function Func(x:real):real;
begin
Func:=-2*x+0.2*x*x;
end;
function Func1(x:real):real;
begin
Func1:=-2.4*x+0.2*x*x;
end;
function Df1(x:real):real;
begin
Df1:=-2+(0.4*x);
end;
function Df2(x:real):real;
begin
Df2:=-2.4+(0.4*x);
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
X1,X2:Real;
Fvek,Fvek2:Real;
L:Real;
B1,B2,B3:real;
DfX2,DfX1:Real;
Eps:Real;
A1,A2,x:real;
Sum:Real;
begin
L:=4;
X1:=StrToFloat(Edit1.Text);
X2:=StrToFloat(Edit2.Text);
Eps:=StrToFloat(Edit3.Text);
Fvek:=Func(X1);
Fvek2:=Func1(X2);
A1:=Fvek+Fvek2;
 repeat
  begin
   repeat
   A1:=Fvek+Fvek2;
    DfX1:=Df1(X1);
    DfX2:=Df2(X2);
    X1:=X1-L*DfX1;
    X2:=X2-L*DfX2;
    Fvek:=Func(X1);
    Fvek2:=Func1(X2);
   A2:= Fvek+Fvek2;
  until A1 > A2;
   DfX1:=Df1(X1);
   DfX2:=Df2(X2);
   b1:=Sqrt(DfX1);
   b2:=Sqrt(DfX2);
   sum:=b1+b2;
 end;
  until sum > Eps ;
 
//Label1.Caption:=FloatToStr();
end;
end.

т.е мне ненужно выводить сообщение о том что число под корнем отрицательное, оно должно считаться и сравниваться с Эпсилонтом в DfX2 значение все равно отрицательное и как его посчитать не знаю.
А решаю задачу многомерной оптимизации состоящую из 7 шагов
1- ввожу X1,X2;
2- нахожу их значения в функции F(X1,X2) у меня

Delphi
1
2
Fvek:=Func(X1);
Fvek2:=Func1(X2);

A1:=Fvek+Fvek2; получаю значение функции
3-нахожу производную для X1,X2

Delphi
1
2
DfX1:=Df1(X1);
DfX2:=Df2(X2);

4-нахожу новый X1,X2 подставл производную в формулу
X1:=X1-L*DfX1;
X2:=X2-L*DfX2;
5-нахожу их значения в функции F(X1,X2) уже с новыми X1,X2

Delphi
1
2
3
Fvek:=Func(X1);
 Fvek2:=Func1(X2);
 A2:= Fvek+Fvek2;

6-проверяю A1 и A2 если A1 >A2 тогда идем дальше если нет то цикл должен выполниться еще раз и уменьшить шаг т.е L:=L/2 это я в коде еще не реализовал
7—нахожу новые производные для X1,X2

Delphi
1
2
DfX1:=Df1(X1);
DfX2:=Df2(X2);

и пытаюсь впихнуть их в корень

Delphi
1
2
3
b1:=Sqrt(DfX1);
 b2:=Sqrt(DfX2);
 sum:=b1+b2;

проверяю условием
sum > Eps то выполняем еще иначе получаем долгожданный ответ.

1

02 апреля 2006 года

kot_

7.3K / / 20.01.2000

Цитата:

Originally posted by Пётр …ович
Код — это, конечно, хорошо. С кодом, оно, конечно, проще. Только код разбросан по файлам.

Ошибку выкидывало тут:

Код:

double TEcology::GetFunctionSignificance (int i)  
{      
     return (FunctionSignificance );  
}

Сейчас немного поправил код (методом Н.Тыка). Пока ошибка не выскакивает. Поглядим на процесс обкатки…

У тебя, в твоем разбросанном коде гдето или выполняется конвертация строки в число или присвоение значения, и при этом не выполняется проверка на региональные установки. Т.е. вместо точки стоит запятая, или наоборот. Например, если региональные установки русские, этот код скорее всего сгенерит исключение:

Код:

double test = StrToFloat(«3.14»);
//примерно тоже будет
test = 3.14;
//примерно так правильно
//Если выбивают ошибки — смотри в хелпы — код пишу по памяти.
char buffer[2]
if(!GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SDECIMAL,buffer,sizeof(buffer))){
 DWORD result = GetLastError();
 …
}
if(strcmp(buffer,»,»)){
double test = StrToFloat(«3,14»);
test = 3,14;
}
else if(strcmp(buffer,».»)){
 …
}

З.Ы. Только без обид — для вопросов на подобные темы есть форум «Сообщества чайников», если актуально — начать стоит с него.

 
Petrovski
 
(2006-10-16 17:22)
[0]

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


 
ANB ©
 
(2006-10-16 17:23)
[1]

Неправильная операция на числом с плавающей точкой.


 
clickmaker ©
 
(2006-10-16 17:24)
[2]

Например, пытаешься из поля типа float получить целое (AsInteger)


 
Stanislav ©
 
(2006-10-16 17:32)
[3]

Я с такой фигней сталкивался, когда запускал приложение под некоторыми win98, на XP было все ок!
Спасало обновление MDAC, либо копирование папки
Program FilesCommon FilesSystem
с рабочей win98 на нерабочую, когда это непомогало, спасала переустановка винды :-)


 
ANB ©
 
(2006-10-16 17:39)
[4]

Проверь типы полей в наборе данных. Скорее всего неправильно определились.


 
clickmaker ©
 
(2006-10-16 18:11)
[5]


> спасала переустановка винды

ну-ну. «Если в кране нет воды, то виной тому — Винды» :)


 
Petr V.Abramov
 
(2006-10-17 01:12)
[6]

это глюк, который м.б. от чего угодно, лечится патчами ADO, windows, программы

> clickmaker ©   (16.10.06 18:11) [5]
 если глючит монитор — микрософт развертку спер
 счет пришел за интернет — вот от микрософта вред :)


 
Stanislav ©
 
(2006-10-17 08:36)
[7]

>clickmaker ©   (16.10.06 18:11) [5]
:-)
Не исключино что комп был заражен червем, может он чего-то наделал.
Разбираться небыло времени, быстрее было винду переставить.


 
ANB ©
 
(2006-10-17 13:03)
[8]


> лечится патчами ADO, windows, программы

и мозгов :)


 
Petrovski
 
(2006-10-17 13:21)
[9]

Никаких видимых нарушений в определении полей не нашел — поля типа Curency  из MS SQL передаются как BCDField, Integer — как IntegerField.
Удалось локализовать источник ошибки. Это вычисляемое поле, в котором  одно BCDField делилось на другое BCDField и умножалось на 100, причем только в том случае, если в числителе был 0.
Почему так — не понимаю.
Спасибо всем за соучастие.


 
ANB ©
 
(2006-10-17 13:34)
[10]


> Petrovski   (17.10.06 13:21) [9]

Вот это уже ближе.
1) Перенеси вычисления на сервер.
2) Имхо — у тебя там и в знаменателе 0. Поставь проверку — если ноль в числителе, то не считать ничего, сразу ноль писать (case).


 
Petrovski
 
(2006-10-17 13:59)
[11]

> ANB [10]

Спасибо!
Я, собственно, и сделал по второму варианту. (Нулей в знаменателе нет). Сейчас попробую и первый вариант реализовать.


Понравилась статья? Поделить с друзьями:

Не пропустите также:

  • Как найти изменение к стандарту
  • Как найти распоряжение правительства российской федерации
  • Как найти синус угла это отношение
  • Гудит кулер в компьютере как исправить видео
  • Скайрим как найти мадези

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии