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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) Image1: TImage; Button1: TButton; Label1: TLabel; Label2: TLabel; Label3: TLabel; Edit1: TEdit; Label4: TLabel; Label5: TLabel; Edit2: TEdit; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; x0, y0:integer; //начало координатных осей l, a, b:integer; x,y,i, ymin, ymax, xmin,xmax:real; dx,mx,my,dy:real; const m = 50; e=0.01; implementation {$R *.dfm} function f(x:real):real; begin result:= sin(x); end; procedure TForm1.Button1Click(Sender: TObject); begin l:=b-a; mx:=410/l; dx:=l/410; ymax:=f(a); ymin:=f(b); i:=a; repeat if f(i)<ymin then ymin:=f(i); if f(i)>ymax then ymax:=f(i); i:=i+dx; until i<=b; my:=440/(ymax-ymin); with Image1 do begin Canvas.Pen.Color:=clWhite; Canvas.Rectangle(0, 0, ClientWidth, ClientHeight); a:=StrToInt(Edit1.Text); b:=StrToInt(Edit2.Text); x0:= 45; y0:= 30; with Canvas do begin Pen.Color:=Clblack;// координатная прямая Pen.Width:= 1; MoveTo(x0,y0); LineTo(x0, Height-y0); MoveTo(x0,Height-y0); LineTo(Width-x0,Height-y0); {*LineTo(45,320); MoveTo(45,320); LineTo(360,320);*} MoveTo(x0,y0); LineTo( x0-3,y0+13); MoveTo(x0,y0); LineTo(x0+3, y0+13 ); {*MoveTo(45,20); LineTo(42,33); MoveTo(45,20); LineTo(48,33);*} MoveTo(Width-x0, Height-y0); LineTo(Width-x0-13, Height-y0+3); MoveTo(Width-x0, Height-y0); LineTo(Width-x0-13, Height-y0-3); {*MoveTo(360,320); LineTo(347,323); MoveTo(360,320); LineTo(347,317); kx:=(Width-90)/(xmax-xmin); ky:=(Height-60)/(ymax-ymin); y:=f(a); x:=a; while a < b do begin a:=a+e; if f(a)< y then begin y:=f(a); x:=a; end;*} Pen.Color:=Clred; Pen.Width:= 2; x:=a; y:=f(x); y0:=440; MoveTo(x0,y0-Trunc(f(x)*my-ymin*my)); repeat x:=x+dx; y:=f(x); LineTo(Trunc(x*mx-a*mx)+x0,y0- Trunc(y*my-ymin*my)); until x>= b ; end; end; end; end. |
Всем привет дорогие читатели блога, а самое главное, любители MapWindow GIS и вообще, любых других геоинформационных систем. Я обещал, что буду постепенно публиковать материал по новой версии MapWindow GIS, поэтому данная небольшая статья для решения одной проблемы с новой версии.
Мне уже задавали этот вопрос, а именно, что когда устанавливают компонент TMap на свою форму, а затем просто при компиляции проекта появляется ошибка: floating point division by zero. Если честно, то я не знаю, в какой момент она возникает. Может это связано с системой координат, либо еще что-то, но решается она очень и очень просто, по крайней мере, я так ее решил. Эту ошибку я наблюдал в Delphi 7, что касается других версий Delphi, я сказать ничего не могу, поэтому ее может просто и не быть.
Поэтому, если после обновления MapWindow GIS до версии 4.9.1 или 4.9.2 у Вас появляется подобная ошибка, то ниже будет описано, как ее можно решить. Мы просто отключим исключения, которые возникают с использованием чисел с плавающей точкой.
Для начала нам нужно объявить константу:
const MCW_EM = DWord($133f);
А затем на событие OnCreate формы, либо можно OnShow пишем следующий код:
Вот и все, как видите, ничего сложного. Теперь нам необходимо просто установить компонент на форму и скомпилировать проект. У меня такой ошибки больше не появляется, и программа отрабатывает на 100 процентов.
I just tried the following code:
procedure TTTest.FormCreate(Sender: TObject);
var v: extended;
one: extended;
begin
one := 1.0;
v := 100*Power(1.25,one);
end;
It just compiles and runs as expected in Delphi 5.
My guess is that the division per zero flag may be set outside your code (even if you do not link to C++ code, calling Direct X or such may have the same effect), but raised later, in _Frac
.
The only call to Frac
in the standard implementation of Power()
is to test Frac(Exponent) = 0.0
.
There was a modification in the implementation of Frac
between Delphi 5 and Delphi 6.
Here is the Delphi 5 version:
procedure _FRAC;
asm
FLD ST(0)
SUB ESP,4
FSTCW [ESP]
FWAIT
FLDCW cwChop
FRNDINT
FWAIT
FLDCW [ESP]
ADD ESP,4
FSUB
end;
Here is the Delphi 6 version:
procedure _FRAC;
asm
FLD ST(0)
SUB ESP,4
FNSTCW [ESP].Word // save
FNSTCW [ESP+2].Word // scratch
FWAIT
OR [ESP+2].Word, $0F00 // trunc toward zero, full precision
FLDCW [ESP+2].Word
FRNDINT
FWAIT
FLDCW [ESP].Word
ADD ESP,4
FSUB
end;
From the above code, you’ll find out that the following commands caused the delayed exceptions to be raised before Delphi 6 was released: Trunc, Frac, Ceil.
So I guess you faced an issue with Delphi 5, which has been fixed with Delphi 6. You may have to use your own version of Power, like this one:
function Power(Base, Exponent: Extended): Extended;
begin
if Exponent = 0.0 then
Result := 1.0 { n**0 = 1 }
else if (Base = 0.0) and (Exponent > 0.0) then
Result := 0.0 { 0**n = 0, n > 0 }
else
Result := Exp(Exponent * Ln(Base))
end;
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Наконец-то! Свершилось чудо! Наконец-то поймался тот самый «Floating point divizion by zero» о котором мне твердили несколько человек с тех самых пор, как я выложил первую версию клиента для DelphiFeeds.ru. Знаете, я бы никогда и ни за что не поверил в то, что когда-нибудь буду радоваться пойманному в своей собственной программе багу…Серьезно. Пытался найти эту ошибку всякими разными способами — таскал программу на работу, проверял на всех подряд компах — нет ошибки! А всего-то надо было…сесть за компьютер жены и запустить программу там и…
Вот он родимый «Floating point divizion by zero» как есть.
Надо сказать, до последнего момента пока не посмотрел отчёт MadExcept относительно этой ошибки, я сомневался: то ли этот баг конкретно мой (хотя никаких делений в программе, в принципе нету), то ли сам стиль глючит. А вот, что мне выдал MadExcept после того как я создал новый проект с Jet Style внутри:
00a374dc +080 Project8.exe FMX.Types 8459 +7 TCanvas.CreateFromBitmap 009b6fdf +01b Project8.exe FMX.Canvas.D2D 688 +1 TCanvasD2D.CreateFromBitmap 00a36f96 +016 Project8.exe FMX.Types 8345 +1 TCanvasManager.CreateFromBitmap 00a3165e +01a Project8.exe FMX.Types 6796 +3 TBitmap.GetCanvas 009d6771 +321 Project8.exe FMX.Platform.Win 1889 +50 TWindowBorderWin.InvalidateRegion 009d6ed2 +06e Project8.exe FMX.Platform.Win 2001 +10 TWindowBorderWin.RecreateRegion 009d8964 +d84 Project8.exe FMX.Platform.Win 2411 +138 WMNCMessages 009d9484 +618 Project8.exe FMX.Platform.Win 2684 +136 WndProc 774b0107 +02b ntdll.dll KiUserCallbackDispatcher 00a73a93 +053 Project8.exe FMX.Forms 3077 +6 TCommonCustomForm.SetWindowState 00a70103 +017 Project8.exe FMX.Forms 1742 +1 TWindowBorder.DoMinClick 00a47791 +17d Project8.exe FMX.Types 13319 +28 TControl.Click 0098d21a +04a Project8.exe FMX.Controls 2468 +14 TCustomButton.Click 00a47cfe +096 Project8.exe FMX.Types 13424 +7 TControl.MouseUp 0098d46f +073 Project8.exe FMX.Controls 2529 +13 TCustomButton.MouseUp 00a70664 +074 Project8.exe FMX.Forms 1857 +4 TWindowBorder.MouseUp 009d88ae +cce Project8.exe FMX.Platform.Win 2379 +106 WMNCMessages 009d9585 +719 Project8.exe FMX.Platform.Win 2710 +162 WndProc 75f87885 +00a USER32.dll DispatchMessageW 009d1b99 +039 Project8.exe FMX.Platform.Win 487 +8 TPlatformWin.HandleMessage 00a6c0c6 +042 Project8.exe FMX.Forms 1328 +3 TApplication.HandleMessage 009d1b0f +02b Project8.exe FMX.Platform.Win 464 +4 TPlatformWin.Run 00a6f486 +0da Project8.exe FMX.Forms 1473 +12 TApplication.Run 00a9ede3 +03b Project8.exe Project8 17 +3 initialization 74d733a8 +010 kernel32.dll BaseThreadInitThunk
После этого отчета мое состояние можно было бы описать примерно так:
Приложение, которое выглядит вот так:
оказалось виновато в том, что оно вообще запустилось (TApplication.Run) и пользователь ткнул мышкой куда-то по форме (куда-то — это на кнопочку минимизации окна). При этом, обращу внимание на тот факт, что демка, идущая в комплекте со стилем работает без ошибок И «секрет» крылся в том, что демо-приложение Embarcadero выглядело вот так:
Т.е свойство EnableBorderStyle было выставлено как False. Стоит его вернуть в True и «Floating point divizion by zero» выскакивает аки чёрт из табакерки. Итак место ошибки было более менее определено — бордюры окна, а точнее стилизованные бордюры окна. Просмотрел стиль на наличие или отсутствие каких-либо элементов бордюра — вроде бы все в норме, размеры TRect’ов выставлены правильно, положение элементов тоже. Полез снова в отчет, начал ковыряться в исходнике FMX и обнаружил место где конкретно срабатывает Exception:
//FMX.Canvas.GDIP.pas constructor TCanvasGdiPlus.CreateFromBitmap(const ABitmap: TBitmap); begin inherited CreateFromBitmap(ABitmap); FGPGraphics := TGPGraphics.Create(TGPBitmap(FBitmap.Handle)); FGPGraphics.SetSmoothingMode(SmothingDefault); FGPGraphics.SetPixelOffsetMode(PixelOffsetModeHalf); FGPGraphics.SetInterpolationMode(InterpolationModeHighQuality); FGPGraphics.SetTextContrast(TextContrast); if GlobalUseGDIPlusClearType then FGPGraphics.SetTextRenderingHint(TextRenderingHintClearTypeGridFit) else FGPGraphics.SetTextRenderingHint(TextRenderingHintAntiAlias); FGPPen := TGPPen.Create($FF000000); FGPPenBrush := TGPSolidBrush.Create($FF000000); FGPBrush := TGPSolidBrush.Create($FFFFFFFF); FGPFamily := TGPFontFamily.Create('Tahoma'); FFontScale := 96 / FGPGraphics.GetDpiX; //ВОТ ТУТ FGPGraphics.GetDpiX = 0
Почему так происходит и когда вызывается этот самый конструктор, скажу откровенно, особенно не искал и в обозримом будущем не планирую — на то есть специально обученные люди. Факт наличия бага есть, баг хоть и не всегда, но воспроизводим. Вполне возможно, что зависит он от видюшки, т.к. у меня стоит ATI Radeon, а у жены на компе — NVidia. Точное место откуда вываливается злосчастный «Floating point divizion by zero» указано. Накорябал баг-репорт…но что-то я его не наблюдаю в этом списке, поэтому, если что — баг остается «вакантным» — можете отправить его в QC повторно Пока же, для тех, кто хочет использовать Jet Style в своих приложениях, небольшой совет:
Не ставьте у приложения с Jet Style свойство формы EnableBorderStyle в значение True — избавите и себя и пользователей от лишнего бага
А я тем временем поисправляю кой-чего в клиенте DelphiFedds.ru, кстати там введена регистрация пользователей, так что скоро нас все посчитают Всем удачи и до новых встреч!
Update. Баг-репорт с описанием ошибки опубликован. Кто встречался с этой ошибкой — голосуйте
Скачать программу можно на форуме.
0
0
голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
← →
Kudatsky
(2002-07-22 10:13)
[0]
Delphi 5 не реагирует на ошибки с плавающей точкой.
Например:
procedure TForm2.Button1Click(Sender: TObject);
Var
A,B,C:Double;
begin
Try
A:=0;
B:=1;
C:=B/A;
Caption:=FloatToStr(C);
Except
Caption:=»Ошибка»;
end;
end;
В этом примере управление не попадает в Except, а в
Caption выводится «INF».
Похоже, что-то с отладчиком ?
← →
IlyaA
(2002-07-22 10:25)
[1]
Посмотри в доке параметры компиляции. Там есть параметр. Ругаться или нет.
← →
IlyaA
(2002-07-22 10:26)
[2]
А с отладчиком всё в порядке. Ошибка в коде (
ГЕНЕТИЧЕСКОМ).
ИЗВИНИ. Злая шутка вырвалась наружу
← →
VICTOR_
(2002-07-22 10:31)
[3]
Прверил, у меня Except обрабатывается. Попробуй поставить break-point на B:=1; и сделать трассировку(F7)
← →
kudatsky
(2002-07-22 10:37)
[4]
За шутку извиню. Но только если подскажешь, какой папаметр.
Иначе буду являться по ночам угрызениями совести ;-)))
← →
kudatsky
(2002-07-22 10:45)
[5]
Кое-что нашёл.
Если снять флажок «Integration debugging»,
Except обрабатывается.
Но в варианте
A:=0;
B:=1;
C:=B/A;
Caption:=FloatToStr(C);
появляется сообщение «Floating point division by zero», а
остановки на строке с ошибкой не происходит
← →
Skier
(2002-07-22 11:30)
[6]
>kudatsky
Debbuger Options|Language Exceptions|Stop on Delphi Exceptions ?
← →
kudatsky
(2002-07-22 11:44)
[7]
Опция
Debbuger Options|Language Exceptions|Stop on Delphi Exceptions
включена
← →
Skier
(2002-07-22 11:50)
[8]
>kudatsky
Debbuger Options|General|Integrated debugging := True
← →
kudatsky
(2002-07-22 11:56)
[9]
Опция Integrated debugging включена.
← →
Skier
(2002-07-22 11:57)
[10]
>kudatsky
И что ? На C:=B/A; не останавливается ?
← →
kudatsky
(2002-07-22 12:02)
[11]
Не останавливается.
В Caption выводится «INF»
Может что на страницах OS Exception или Language Exception ?
← →
Skier
(2002-07-22 12:08)
[12]
>kudatsky
У тебя в списке Exceptions на странице OS Exception есть
Float Devide By Zero ?
← →
Viewer
(2002-07-22 12:10)
[13]
INF — infinity (так Борланд реагирует на эти шутки)
← →
kudatsky
(2002-07-22 12:11)
[14]
Есть.
User program:=true
Run unhandled:=true
← →
IlyaA
(2002-07-22 13:07)
[15]
В блоке try-except попробуй-
try
a:=b/0;
except
on EDivByZero do ShowMessage(«Error»);
end;
← →
kudatsky
(2002-07-22 13:43)
[16]
Сделал.
Исключение не возбуждается.
← →
IlyaA
(2002-07-22 13:45)
[17]
Похоже у тебя уже всё
упало.
← →
kudatsky
(2002-07-22 13:52)
[18]
Только-что инстолировал D5 на другую машину. То же самое. Что интересно, никакой реакции на
on E: Exception do ShowMessage(«Error»);
Может Delphi с глюками ?
← →
Слесарь Матерящийся
(2002-07-22 13:59)
[19]
Может, дело в точности представления вещественного числа?
То есть, присваиваем чистый 0, а получаем 0 + погрешность, и в результате не-ноль.
Попробуйте то же самое с целыми числами.
← →
IlyaA
(2002-07-22 14:01)
[20]
Вот енто из хэлпы. Может что и прояснит
EIntError is the base class for integer math error exceptions.
Unit
SysUtils
Description
EIntError is a generic integer math exception. Although it is never raised in the runtime library, it is the base from which other integer math exceptions descend. These are the integer math exceptions:
Exception Meaning
EDivByZero An attempt was made to divide by zero
ERangeError Number or expression out of range
EIntOverflow Integer operation overflowed
Run-time exception information is saved in fields provided by EExternal.
← →
kudatsky
(2002-07-22 14:02)
[21]
С целыми числами всё в порядке, я уже пробовал.
← →
Слесарь Матерящийся
(2002-07-22 15:11)
[22]
То-то и оно!
← →
kudatsky
(2002-07-22 15:19)
[23]
????????????????
← →
tall
(2002-07-22 16:00)
[24]
Я эту тему пеоднимал уже несколько раз. Кстати и в этой конфе тоже. Куда только не писал. Вразумительный ответ дали только в AMD (у меня эти глюки начались после того как пересел с Pentium 200MMX на AMD 1200. Думал может связано сплатформой). Там мне сказали, что это не глюк, а изменения в компиляторе в соответствии с требованиями новых стандартов ( типа ответ +INF или -INF (бесконечность) и тому подобное это не исключительная ситуация а нормальное явление). И отослели к технической документации по процессору( там, кстати, это действительно написано). Судя по всему это относится и Pentium платформе (мне писали об аналогичных проблемах на Celeron), т.е. характерно для всех новых процессоров. Решить эту проблему удалось только откатившись на DELPHI 4. Чего и вам советую.
← →
kudatsky
(2002-07-23 10:27)
[25]
tall, если Вы ещё здесь!
Где это можно прочитать ?
← →
VICTOR_
(2002-07-23 11:48)
[26]
У тебя материнка на VIA логике?
← →
Viewer
(2002-07-23 12:24)
[27]
ffmt.asm
; INF and NAN strings
INFNAN DB «INFNAN»
; function FloatToText(Buffer: PChar; const Value; ValueType: TFloatValue;
; Format: TFloatFormat; Precision, Digits: Integer): Integer;
sysutils.pas
function TextToFloat(Buffer: PChar; var Value;
ValueType: TFloatValue): Boolean;
{ FloatToDecimal converts a floating-point value to a decimal representation
that is suited for further formatting. The Value parameter must be a
variable of type Extended or Currency, as indicated by the ValueType
parameter. For values of type Extended, the Precision parameter specifies
the requested number of significant digits in the result—the allowed range
is 1..18. For values of type Currency, the Precision parameter is ignored,
and the implied precision of the conversion is 19 digits. The Decimals
parameter specifies the requested maximum number of digits to the left of
the decimal point in the result. Precision and Decimals together control
how the result is rounded. To produce a result that always has a given
number of significant digits regardless of the magnitude of the number,
specify 9999 for the Decimals parameter. The result of the conversion is
stored in the specified TFloatRec record as follows:
Exponent — Contains the magnitude of the number, i.e. the number of
significant digits to the right of the decimal point. The Exponent field
is negative if the absolute value of the number is less than one. If the
number is a NAN (not-a-number), Exponent is set to -32768. If the number
is INF or -INF (positive or negative infinity), Exponent is set to 32767.
Negative — True if the number is negative, False if the number is zero
or positive.
Digits — Contains up to 18 (for type Extended) or 19 (for type Currency)
significant digits followed by a null terminator. The implied decimal
point (if any) is not stored in Digits. Trailing zeros are removed, and
if the resulting number is zero, NAN, or INF, Digits contains nothing but
the null terminator. }