Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ «О Ρ‡Ρ‘ΠΌ Π½Π΅ ΠΏΠΈΡˆΡƒΡ‚ Π² ΠΊΠ½ΠΈΠ³Π°Ρ… ΠΏΠΎ DelphiΒ». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 100

Автор А. Π“Ρ€ΠΈΠ³ΠΎΡ€ΡŒΠ΅Π²

Π’ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ описанная ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° с ΠΏΠΎΡ‚Π΅Ρ€Π΅ΠΉ точности встрСчаСтся всС Ρ€Π΅ΠΆΠ΅, Π΅ΡΡ‚ΡŒ заслуга ΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² VCL. Зная, Π²Ρ‹Π·ΠΎΠ²Ρ‹ ΠΊΠ°ΠΊΠΈΡ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΌΠΎΠ³ΡƒΡ‚ привСсти ΠΊ измСнСнию ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‰Π΅Π³ΠΎ слова FPU, ΠΎΠ½ΠΈ ΠΏΠ΅Ρ€Π΅Π΄ этими Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°ΡŽΡ‚ ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‰Π΅Π΅ слово, Π° Π·Π°Ρ‚Π΅ΠΌ Π²ΠΎΡΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°ΡŽΡ‚. Π’ Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ·Π΄Π½ΠΈΡ… вСрсиях Delphi количСство Ρ‚Π°ΠΊΠΈΡ… "ΠΎΠ±Π΅Ρ€Ρ‚ΠΎΠΊ" большС, Ρ‡Π΅ΠΌ Π² Ρ€Π°Π½Π½ΠΈΡ…, поэтому Ρ‡Π΅ΠΌ Π½ΠΎΠ²Π΅Π΅ вСрсия Delphi, Ρ‚Π΅ΠΌ мСньшС шанс ΡΡ‚ΠΎΠ»ΠΊΠ½ΡƒΡ‚ΡŒΡΡ с описанной ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ. Π—Π΄Π΅ΡΡŒ ΠΌΡ‹ рассмотрим нСсколько ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ² ΠΈΠ· исходного ΠΊΠΎΠ΄Π° стандартных ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ Delphi 2007.

Для динамичСской Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ DLL ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½Π° API-функция LoadLibrary. Π’ ΠΌΠΎΠ΄ΡƒΠ»Π΅ SysUtils для этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ прСдлагаСтся ΠΎΠ±Π΅Ρ€Ρ‚ΠΊΠ°, Π½Π°Π·Ρ‹Π²Π°ΡŽΡ‰Π°ΡΡΡ SafeLoadLibrary (листинг 3.13).

Листинг 3.13. Ѐункция SysUtils.SafeLoadLibrary

{ SafeLoadLibrary calls LoadLibrary, disabling normal Win32 error message popup dialogs if the requested file can't be loaded. SafeLoadLibrary also preserves the current FPU control word (precision, exception masks) across the LoadLibrary call (in case the DLL you're loading hammers the FPU control word in its initialization, as many MS DLLs do) }

function SafeLoadLibrary(const Filename: string; ErrorMode: UINT): HMODULE;

var

 OldMode: UINT;

 FPUControlWord: Word;

begin

 OldMode := SetErrorMode(ErrorMode); 

 try

  asm

   FNSTCW FPUControlWord

  end;

  try

   Result := LoadLibrary(PChar(Filename));

  finally

   asm

    FNCLEX

    FLDCW FPUControlWord

   end;

  end;

 finally

  SetErrorMode(OldMode);

 end;

end;

Как Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· коммСнтария, ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΠ΅ систСмныС Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ΠΈΠ·ΠΌΠ΅Π½ΡΡŽΡ‚ ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‰Π΅Π΅ слово FPU ΠΏΡ€ΠΈ своСй ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ.

Π’ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ CreateADOObject (внутрСнняя функция модуля ADODB) Ρ‚ΠΎΠΆΠ΅ сохраняСтся ΠΈ восстанавливаСтся ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‰Π΅Π΅ слово (листинг 3.14).

Листинг 3.14. Ѐункция CreateADOObject модуля ADODB

function CreateADOObject(const ClassID: TGUID): IUnknown;

var

 Status: HResult;

 FPUControlWord: Word;

begin

 asm

  FNSTCW FPUControlWord

 end;

 Status :=

  CoCreateInstance(ClassID, nil, CLSTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IUnknown, Result);

 asm

  FNCLEX

  FLDCW FPUControlWord

 end;

 if (Status = REGDB_E_CLASSNOTREG) then

  raise Exception.CreateRes(@SADOCreateError)

 else OleCheck(Status);

end;

Π—Π΄Π΅ΡΡŒ Π²ΠΎΡΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Ρ‚ΡŒ ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‰Π΅Π΅ слово приходится послС Π²Ρ‹Π·ΠΎΠ²Π° систСмной Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ CoCreateInstance, ΡΠΎΠ·Π΄Π°ΡŽΡ‰Π΅ΠΉ БОМ-ΠΎΠ±ΡŠΠ΅ΠΊΡ‚. Но, судя ΠΏΠΎ Ρ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ большС Π½ΠΈΠ³Π΄Π΅ ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ CoCreateInstance Ρ‚Π°ΠΊΠΎΠΉ ΠΊΠΎΠ΄ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ, ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π½Π΅ Π² самой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π° Π² Ρ‚Π΅Ρ… ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹Ρ… ADO-ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ здСсь с Π΅Π΅ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ.

ΠΠ½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΡƒΡŽ Π·Π°Ρ‰ΠΈΡ‚Ρƒ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΡ‚ΡŒ Π² ΠΌΠΎΠ΄ΡƒΠ»Π΅ Dialogs, Π² ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ TCommonDialog.TaskModalDialog. ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ ΠΊ этой Π·Π°Ρ‰ΠΈΡ‚Π΅ гласит: "Avoid FPU control word change in NETRAP.dll, NETAPI32.dll, etc".

Π’ ΠΌΠΎΠ΄ΡƒΠ»Π΅ Windows особым ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ΡΡ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ CreateWindow ΠΈ CreateWindowEx, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅, Π²ΠΈΠ΄ΠΈΠΌΠΎ, Ρ‚ΠΎΠΆΠ΅ Π±Ρ‹Π»ΠΈ Π·Π°ΠΌΠ΅Ρ‡Π΅Π½Ρ‹ Π² Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ с ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‰ΠΈΠΌ словом FPU. Π’ΠΎΡ‚ ΠΊΠ°ΠΊ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, выглядит ΠΈΠΌΠΏΠΎΡ€Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ CreateWindowEx (листинг 3.15).

Листинг 3.15. Π˜ΠΌΠΏΠΎΡ€Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ CreateWindowEx ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΌ Windows

function _CreateWindowEx(dwExStyle: WORD; lpClassName: PChar; lpWindowName: PChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer; hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND; stdcall; external user32 name 'CreateWindowExA';


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 ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ CreateWindowExA ΠΈΠ· Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ user32.dll, Π½ΠΎ Π΄Π°Π΅Ρ‚ Π΅ΠΉ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½Π½ΠΎΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΠΈ Π½Π΅ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π΅Π΅ Π² своСм интСрфСйсС. ВмСсто этого ΠΎΠ½ экспортируСт Π΄Ρ€ΡƒΠ³ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ с Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ CreateWindowEx (ΠΈ Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΡƒΡŽ с Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ CreateWindowExA), которая являСтся ΠΎΠ±Π΅Ρ€Ρ‚ΠΊΠΎΠΉ Π½Π°Π΄ настоящСй CreateWindowExA ΠΈ обСспСчиваСт сохранСниС значСния ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‰Π΅Π³ΠΎ слова FPU. Аналогичным способом импортируСтся ΠΈ Unicode-Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, стандартныС Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°ΡŽΡ‚ Π²Ρ‹Π·ΠΎΠ² бСзопасного Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π° CreateWindowEx Π² любой ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅.

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅

Π’ ΠΌΠΎΠ΄ΡƒΠ»Π΅ Windows ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΡ‚ΡŒ Π΅Ρ‰Π΅ ΠΎΠ΄Π½Ρƒ ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΠ½ΡƒΡŽ Π΄Π΅Ρ‚Π°Π»ΡŒ: Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ CreateWindowA ΠΈ CreateWindowW ΠΈΠ· Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ user32.dll этим ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΌ Π²ΠΎΠΎΠ±Ρ‰Π΅ Π½Π΅ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ΡΡ. ВмСсто этого ΠΎΠ΄Π½ΠΎΠΈΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΎΠ±Π΅Ρ€Ρ‚ΠΊΠΈ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‚ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ _CreateWindowExA ΠΈ _CreateWindowExW, пСрСдавая ΠΈΠΌ 0 Π² качСствС значСния ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° dwExStyle.

3.2.12. МашинноС эпсилон

Когда ΠΌΡ‹ ΠΈΠΌΠ΅Π΅ΠΌ Π΄Π΅Π»ΠΎ с вычислСниями с ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Π½ΠΎΠΉ Ρ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒΡŽ, Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ Ρ‚Π°ΠΊΠΎΠΉ парадокс. ΠŸΡƒΡΡ‚ΡŒ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΌΡ‹ считаСм с Ρ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒΡŽ Π΄ΠΎ Ρ‚Ρ€Π΅Ρ… Π·Π½Π°Ρ‡Π°Ρ‰ΠΈΡ… Ρ†ΠΈΡ„Ρ€. ΠŸΡ€ΠΈΠ±Π°Π²ΠΈΠΌ ΠΊ числу 1,00 число 1,00Ξ‡10-4. Если Π±Ρ‹ всС Π±Ρ‹Π»ΠΎ чСстно, ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ Π±Ρ‹ 1,0001. Но Ρƒ нас ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Π° Ρ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ, поэтому ΠΌΡ‹ Π²Ρ‹Π½ΡƒΠΆΠ΄Π΅Π½Ρ‹ ΠΎΠΊΡ€ΡƒΠ³Π»ΡΡ‚ΡŒ Π΄ΠΎ Ρ‚Ρ€Π΅Ρ… Π·Π½Π°Ρ‡Π°Ρ‰ΠΈΡ… Ρ†ΠΈΡ„Ρ€. Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ получаСтся 1,00. Π”Ρ€ΡƒΠ³ΠΈΠΌΠΈ словами, ΠΊ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ числу ΠΌΡ‹ прибавляСм Π΄Ρ€ΡƒΠ³ΠΎΠ΅ число, большСС нуля, Π° Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ ΠΈΠ·-Π·Π° ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Π½ΠΎΠΉ точности ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Ρ‚ΠΎ ΠΆΠ΅ самоС число. НаимСньшСС ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ число, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΏΡ€ΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠΈ Π΅Π³ΠΎ ΠΊ Π΅Π΄ΠΈΠ½ΠΈΡ†Π΅ Π΄Π°Π΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π½Π΅ Ρ€Π°Π²Π½Ρ‹ΠΉ Π΅Π΄ΠΈΠ½ΠΈΡ†Π΅, называСтся ΠΌΠ°ΡˆΠΈΠ½Π½Ρ‹ΠΌ эпсилон.

ΠŸΠΎΠ½ΡΡ‚ΠΈΠ΅ машинного эпсилон Ρƒ Π½ΠΎΠ²ΠΈΡ‡ΠΊΠΎΠ² Π½Π΅Ρ€Π΅Π΄ΠΊΠΎ путаСтся с понятиСм наимСньшСго числа, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ записано Π² Π²Ρ‹Π±Ρ€Π°Π½Π½ΠΎΠΌ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅. Π­Ρ‚ΠΎ Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ. МашинноС эпсилон опрСдСляСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠΌ мантиссы, Π° минимально Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠ΅ число оказываСтся сущСствСнно мСньшС ΠΈΠ·-Π·Π° сдвига ΠΏΠ»Π°Π²Π°ΡŽΡ‰Π΅ΠΉ Π΄Π²ΠΎΠΈΡ‡Π½ΠΎΠΉ Ρ‚ΠΎΡ‡ΠΊΠΈ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ экспонСнты.

ΠŸΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ ΠΈΡΠΊΠ°Ρ‚ΡŒ машинноС эпсилон ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎ, попытаСмся Π½Π°ΠΉΡ‚ΠΈ Π΅Π³ΠΎ ΠΈΠ· тСорСтичСских сообраТСний. Π˜Ρ‚Π°ΠΊ, мантисса Ρ‚ΠΈΠΏΠ° Extended содСрТит 64 разряда. Π§Ρ‚ΠΎΠ±Ρ‹ Π·Π°ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ, ΡΡ‚Π°Ρ€ΡˆΠΈΠΉ Π±ΠΈΡ‚ мантиссы Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Ρ€Π°Π²Π΅Π½ 1 (дСнормализованная запись), ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ Π±ΠΈΡ‚Ρ‹ β€” Π½ΡƒΠ»ΡŽ. ΠžΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈ Ρ‚Π°ΠΊΠΎΠΉ записи наимСньшСС ΠΈΠ· чисСл, для ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… выполняСтся условиС x > 1, получаСтся, ΠΊΠΎΠ³Π΄Π° самый младший Π±ΠΈΡ‚ мантиссы Ρ‚ΠΎΠΆΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π²Π΅Π½ Π΅Π΄ΠΈΠ½ΠΈΡ†Π΅, Ρ‚.Π΅. Ρ… = 1,00...001 (Π² Π΄Π²ΠΎΠΈΡ‡Π½ΠΎΠΌ прСдставлСнии, ΠΌΠ΅ΠΆΠ΄Ρƒ Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ ΠΈ младшСй Π΅Π΄ΠΈΠ½ΠΈΡ†Π΅ΠΉ 62 нуля). Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, машинноС эпсилон Ρ€Π°Π²Π½ΠΎ Ρ…-1, Ρ‚.Π΅. 0.00...001. Π’ Π±ΠΎΠ»Π΅Π΅ ΠΏΡ€ΠΈΠ²Ρ‹Ρ‡Π½ΠΎΠΉ дСсятичной Ρ„ΠΎΡ€ΠΌΠ΅ записи это Π±ΡƒΠ΄Π΅Ρ‚ 2-63, Ρ‚.Π΅. ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ 1,084Ξ‡10-19.

Листинг 3.16 ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ это число (ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Epsilon Π½Π° ΠΊΠΎΠΌΠΏΠ°ΠΊΡ‚-дискС).

Листинг 3.16. Поиск машинного эпсилон

procedure TForm1.Button1Click(Sender: TObject);

var

 R: Extended;

 I: Integer;

begin

 R := 1;

 while 1 + R/2 > 1 do R := R / 2;

 Label1.Caption := FloatToStr(R);

end;

Запустив этот ΠΊΠΎΠ΄, ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ Π½Π° экранС 1.0842021724855Π•-19 Π² ΠΏΠΎΠ»Π½ΠΎΠΌ соотвСтствии с нашими тСорСтичСскими Π²Ρ‹ΠΊΠ»Π°Π΄ΠΊΠ°ΠΌΠΈ.

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅

Π’ Ρ‚Π΅Ρ… систСмах, Π³Π΄Π΅ Π½Π°Π±Π»ΡŽΠ΄Π°Π΅Ρ‚ΡΡ описанная ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° с ΡƒΠΌΠ΅Π½ΡŒΡˆΠ΅Π½ΠΈΠ΅ΠΌ точности, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° выдаст 2.22044604925031Π•-16. Если Π²Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Π»ΠΈ Ρƒ сСбя это число, Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ ΠΊΠΎΠ΄, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠ΅Ρ€Π΅Π²Π΅Π΄Π΅Ρ‚ FPU Π² Ρ€Π΅ΠΆΠΈΠΌ максимальной точности.

А Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΈΠ·ΠΌΠ΅Π½ΠΈΠΌ Ρ‚ΠΈΠΏ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ R с Extended Π½Π° Double. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π½Π΅ измСнится. На Single β€” ΠΎΠΏΡΡ‚ΡŒ Π½Π΅ измСнится. Но Ρ‚Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ лишь Π½Π° ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ взгляд ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ странным. Π”Π°Π²Π°ΠΉΡ‚Π΅ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ рассмотрим Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ 1 + R / 2 > 1. Π˜Ρ‚Π°ΠΊ, всС вычислСния (Π² Ρ‚ΠΎΠΌ числС ΠΈ сравнСниС) сопроцСссор выполняСт с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ Ρ‚ΠΈΠΏΠ° Extended. ΠŸΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ дСйствий Ρ‚Π°ΠΊΠΎΠ²Π°: число R загруТаСтся Π² рСгистр сопроцСссора, ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΡΡΡŒ ΠΏΡ€ΠΈ этом ΠΊ Ρ‚ΠΈΠΏΡƒ Extended. Π”Π°Π»ΡŒΡˆΠ΅ ΠΎΠ½ΠΎ дСлится Π½Π° 2, Π° Π·Π°Ρ‚Π΅ΠΌ ΠΊ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ прибавляСтся 1, ΠΈ всС это Π² Extended, Π½ΠΈΠΊΠ°ΠΊΠΎΠ³ΠΎ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ прСобразования Π² Single ΠΈΠ»ΠΈ Double Π½Π΅ происходит. Π—Π°Ρ‚Π΅ΠΌ это число сравниваСтся с Π΅Π΄ΠΈΠ½ΠΈΡ†Π΅ΠΉ. ΠžΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ сравнСния Π½Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π·Π°Π²ΠΈΡΠ΅Ρ‚ΡŒ ΠΎΡ‚ исходного Ρ‚ΠΈΠΏΠ° R, Ρ‚.ΠΊ. Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π° Π΄Π°ΠΆΠ΅ Ρ‚ΠΈΠΏΠ° Single Π²ΠΏΠΎΠ»Π½Π΅ Ρ…Π²Π°Ρ‚Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π°Π·ΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ машинноС эпсилон.

3.2.13. ΠœΠ΅Ρ‚ΠΎΠ΄Ρ‹ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ

ПодвСдСм ΠΈΡ‚ΠΎΠ³ΠΈ сказанному. ЗначСния, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ, ΠΌΠΎΠ³ΡƒΡ‚ ΠΎΡ‚Π»ΠΈΡ‡Π°Ρ‚ΡŒΡΡ ΠΎΡ‚ ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌΡ‹Ρ…, Π΄Π°ΠΆΠ΅ Ссли Ρ€Π΅Ρ‡ΡŒ ΠΈΠ΄Π΅Ρ‚ ΠΎ простом присваивании. Π’ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΡ… случаях (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² Π½Π°ΡƒΡ‡Π½Ρ‹Ρ… расчСтах) это нСсущСствСнно, Ρ‚.ΠΊ. сам ΠΌΠ΅Ρ‚ΠΎΠ΄ расчСта Π΄Π°Π΅Ρ‚ Π΅Ρ‰Π΅ Π±ΠΎΠ»ΡŒΡˆΡƒΡŽ ΠΏΠΎΠ³Ρ€Π΅ΡˆΠ½ΠΎΡΡ‚ΡŒ. ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‚ΡΡ Ρ‚Π°ΠΌ, Π³Π΄Π΅ ΠΌΡ‹ Ρ…ΠΎΡ‚ΠΈΠΌ вывСсти число Π½Π° экран ΠΈΠ»ΠΈ ΡΡ€Π°Π²Π½ΠΈΡ‚ΡŒ Π΅Π³ΠΎ с Π΄Ρ€ΡƒΠ³ΠΈΠΌ. Π£Π½ΠΈΠ²Π΅Ρ€ΡΠ°Π»ΡŒΠ½Ρ‹Ρ… Ρ€Π΅Ρ†Π΅ΠΏΡ‚ΠΎΠ² Π½Π° всС случаи ΠΆΠΈΠ·Π½ΠΈ Π½Π΅ сущСствуСт, Π½ΠΎ Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΡ… ситуациях ΠΏΠΎΠΌΠΎΠ³Π°ΡŽΡ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ совСты:

β–‘ Π•сли ваша Π·Π°Π΄Π°Ρ‡Π° β€” просто ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ "красивоС" прСдставлСниС числа Π½Π° экранС, Ρ‚ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ FloatToStr замСняйтС Π½Π° Π΅Π΅ Π±ΠΎΠ»Π΅Π΅ ΠΌΠΎΡ‰Π½Ρ‹ΠΉ Π°Π½Π°Π»ΠΎΠ³ FloatToStrF ΠΈΠ»ΠΈ Π½Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Format β€” ΠΎΠ½ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΆΠ΅Π»Π°Π΅ΠΌΠΎΠ΅ количСство символов послС Ρ‚ΠΎΡ‡ΠΊΠΈ.

β–‘ Π‘Ρ€Π°Π²Π½Π΅Π½ΠΈΠ΅ вСщСствСнных чисСл слСдуСт Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ с ΡƒΡ‡Π΅Ρ‚ΠΎΠΌ ΠΏΠΎΠ³Ρ€Π΅ΡˆΠ½ΠΎΡΡ‚ΠΈ, Ρ‚.Π΅. вмСсто if Π° = b … ΠΏΠΈΡΠ°Ρ‚ΡŒ if Abs(Π° - b) < Π•Ρ€s …, Π³Π΄Π΅ Eps β€” нСкоторая Π²Π΅Π»ΠΈΡ‡ΠΈΠ½Π°, Π·Π°Π΄Π°ΡŽΡ‰Π°Ρ Π΄ΠΎΠΏΡƒΡΡ‚ΠΈΠΌΡƒΡŽ ΠΏΠΎΠ³Ρ€Π΅ΡˆΠ½ΠΎΡΡ‚ΡŒ (Π² ΠΌΠΎΠ΄ΡƒΠ»Π΅ Math, начиная с Delphi 6, сущСствуСт функция SameValue, с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ это ΠΆΠ΅ условиС ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΊΠ°ΠΊ if SameValue(a, b, Eps) …).