Delphi浮點常量與浮點變量邏輯值相同但對比失敗的解決辦法

直接看代碼(運行環境Win10+XE8)
api

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

const
  //誤差範圍 由於個人常量以及變量都只有一位小數,因此誤差在0.01便認爲可接受
  //實際誤差值請根據須要自行調整
  DEVIATION_GRADE = 0.01;
  //範圍值最大值常量 Delphi默認把浮點類型常量歸於 System.Extended類型
  //網上說Double佔用8個字節,而Extended佔用10個字節,因此Extended比Double類型精度更高
  VALUE_MAX_C = 4.2;
  //範圍值最小值常量
  VALUE_MIN_C = 3.9;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  //若下面的變量定義爲AValue: Extended; 則能夠不使用偏差判斷,直接比對便可,由於兩個值精度相同
  AValue: Double;
begin
  //先把界面輸入的值轉換成一個Double類型變量,供後續判斷使用
  //雖然這個函數的名字叫TryStrToFloat,可是實際上它返回的值爲System.Extended類型
  //因此另一個解決辦法就是把AValue定義爲System.Extended類型,這樣就不會出現不一致的狀況
  if not TryStrToFloat(Trim(Edit1.Text), AValue) then
  begin
    Memo1.Lines.Add('轉換失敗');
    Exit;
  end;

  //若界面的值輸入的爲3.9或4.2,則直接比對時會致使比對失敗
  if (AValue >= VALUE_MIN_C) and (AValue <= VALUE_MAX_C) then
    Memo1.Lines.Add('直接比對 between 3.9 and 4.2')
  else
    Memo1.Lines.Add('直接比對失敗');

  //界面的值輸入爲3.9時,咱們認爲它應該>=常量3.9,但實際這個判斷返回的是false
  if (AValue >= VALUE_MIN_C) then
    Memo1.Lines.Add('直接比對 AValue >= VALUE_MIN_C');
  if (AValue <= VALUE_MAX_C) then
    Memo1.Lines.Add('直接比對 AValue <= VALUE_MAX_C');

  //使用允差比對就能夠解決上面的問題
  //當變量值爲3.9時,常量3.9-偏差0.01=3.89,條件AValue > VALUE_MIN_C - DEVIATION_GRADE成立
  //當變量值爲4.2時,變量值4.2-偏差0.01=4.19,條件AValue - DEVIATION_GRADE <= VALUE_MAC_C成立
  if (AValue >= VALUE_MIN_C - DEVIATION_GRADE) and (AValue - DEVIATION_GRADE <= VALUE_MAX_C) then
    Memo1.Lines.Add('誤差比對 between 3.9 and 4.2')
  else
    Memo1.Lines.Add('誤差比對失敗');
end;

end.

窗體文件函數

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 242
  ClientWidth = 527
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Memo1: TMemo
    Left = 200
    Top = 24
    Width = 169
    Height = 129
    Lines.Strings = (
      'Memo1')
    TabOrder = 0
  end
  object Edit1: TEdit
    Left = 48
    Top = 32
    Width = 121
    Height = 21
    TabOrder = 1
    Text = '4.2'
  end
  object Button1: TButton
    Left = 200
    Top = 168
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 2
    OnClick = Button1Click
  end
end

究其緣由,應該是由於Double類型與Extended在內存中表示的方式不一致致使,因此解決辦法有兩個:工具

  1. 把變量改爲和系統常量相同的類型,即把變量定義爲Extended類型調試

  2. 使用合理的偏差值計算結果,一樣能夠避免該問題
    code


PS:不知道各位大神誰會使用Delphi的調試工具呀?能不能在運行時看看常量以及變量的值再內存中是如何表示的?既然他們不一樣,那麼不一樣處在哪兒?求解答!!!orm

相關文章
相關標籤/搜索