bestlong 怕失憶論壇

 

 

搜索
bestlong 怕失憶論壇 論壇 Delphi Round 函數不正確的四捨五入狀況
查看: 19302|回復: 7
go

Round 函數不正確的四捨五入狀況 [複製鏈接]

Rank: 9Rank: 9Rank: 9

1#
發表於 2007-3-7 10:49 |只看該作者 |倒序瀏覽 |打印
  1. Delphi 的 Round() 四捨五入函數採奇入偶捨方式, Ex:

  2.   Round(1.5) => 2
  3.   Round(2.5) => 2
  4.   Round(3.5) => 4

  5. 2.5 得到的結果怎麼會是 2 呢?

  6. 解決之道: 自己寫四捨五入函數, 以下提供兩種:

  7.   方法一:

  8.     function MyRound(P: Double; Decimals: integer): Double;
  9.     var
  10.       factor: LongInt;
  11.       help: Double;
  12.       i: integer;
  13.     begin
  14.       factor := 1;
  15.       for i := 1 to decimals do
  16.         factor := factor * 10;
  17.   
  18.       if P < 0 then
  19.         help := -0.5
  20.       else
  21.         help := 0.5;
  22.       Result := Int(P*factor+help) / factor;
  23.       if (Result > -0.00000001) and (Result < 0.00000001) then
  24.         Result := 0.00;
  25.     end;

  26.   方法二: 利用 FloatToStrF 及 StrToFloat 函數:
  27.    
  28.     function MyRound(P: Double; Decimals: integer): Double;
  29.     var
  30.       s: string;
  31.     begin
  32.       s := FloatToStrF(P, ffFixed, 15, Decimals)
  33.       Result := StrToFloat(s);
  34.     end;
複製代碼
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw

Rank: 9Rank: 9Rank: 9

2#
發表於 2007-4-4 15:22 |只看該作者
在Delphi中使用Round函數得到的答案有時與我們所預期的會不太一樣:

採用的是四捨六入五留雙。即當捨去或進位大於或小於五時按四捨五入來處理,而當捨去或進位等於五時,就要看前面一位是什麼,根據根据奇進偶不進,它總是返回一個偶數值。

     範例             結果
i:= Round(11.5)        12
i:= Round(10.5)        10

這種Round其實是按照銀行家演算法,統計學上一般都用這種算法,比傳統的"四捨五入"要科學。
如果要使用傳統的"四捨五入"方法,可以使用下面函數:
  1. function RoundClassic(R: Real): Int64;
  2. begin
  3.   Result:= Trunc(R);
  4.   if Frac(R) >= 0.5 then
  5.     Result := Result + 1;
  6. end;
複製代碼
其實在VB、Excel、.NET相關的語言中都有這個問題。
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw

Rank: 9Rank: 9Rank: 9

3#
發表於 2009-12-17 09:16 |只看該作者
從 Delphi 6 開始可以使用 SimpleRoundTo() 函數來處理四捨五入,而 Delphi 5 環境就需要自己補上,不過可以參考 D6 或 D7 的程式碼。
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw

Rank: 9Rank: 9Rank: 9

4#
發表於 2010-5-26 20:56 |只看該作者
四捨五入喔,不要再忘記了~

From http://jasper-dale.spaces.live.c ... E92E2726C!470.entry

每次要用到 四捨五入 都忘記是那個指令!

function Round(X: Extended): Int64;

If X is exactly halfway between two whole numbers, the result is always the even number.
如果X剛好在兩數的中間,那回傳的數將會是 "偶數" 的那一個。
This method of rounding is often called "Banker's Rounding".
我才不管什麼 "Banker's Rounding" ,實用最重要。
在網路上找到很多資訊,加以小改一下成為台灣適用的『四捨五入』
就呼叫自己的 RoundF 吧!
  1. function RoundF(X: Extended; Decimal: integer = 0): Extended;
  2. var
  3.   PowerNum: Extended;
  4. begin
  5.   PowerNum := IntPower(10, Decimal);
  6.   Result := RoundI(X * PowerNum) / PowerNum;
  7. end;

  8. function RoundI(X: Extended): Int64;
  9. begin
  10.   if X < 0 then
  11.     Result := Round(X - 0.0000001)
  12.   else
  13.     Result := Round(X + 0.0000001);
  14. end;
複製代碼
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw

Rank: 9Rank: 9Rank: 9

5#
發表於 2011-3-8 11:49 |只看該作者
參考樓上的修改成這樣
  1. function RoundF(X: Extended; Decimal: integer = 2): Extended;
  2. var
  3.   PowerNum: Extended;
  4. begin
  5.   PowerNum := IntPower(10, Decimal);
  6.   if X < 0 then
  7.     Result := Round((X * PowerNum) - 0.1) / PowerNum
  8.   else
  9.     Result := Round((X * PowerNum) + 0.1) / PowerNum;
  10. end;
複製代碼
測試程式
  1. unit Unit1;

  2. interface

  3. uses
  4.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  5.   StdCtrls, Math;

  6. type
  7.   TForm1 = class(TForm)
  8.     Memo1: TMemo;
  9.     procedure FormCreate(Sender: TObject);
  10.   private
  11.     { Private declarations }
  12.   public
  13.     { Public declarations }
  14.   end;

  15. var
  16.   Form1: TForm1;

  17. implementation

  18. {$R *.DFM}

  19. function RoundF(X: Extended; Decimal: integer = 2): Extended;
  20. var
  21.   PowerNum: Extended;
  22. begin
  23.   PowerNum := IntPower(10, Decimal);
  24.   if X < 0 then
  25.     Result := Round((X * PowerNum) - 0.1) / PowerNum
  26.   else
  27.     Result := Round((X * PowerNum) + 0.1) / PowerNum;
  28. end;

  29. procedure TForm1.FormCreate(Sender: TObject);
  30. var
  31.   f: Double;
  32. begin
  33.   Memo1.Clear;
  34.   f := 1213.245;
  35.   Memo1.Lines.Append(floattostr(f));
  36.   Memo1.Lines.Append(FloatToStr(RoundF(1213.245, 2)));
  37.   Memo1.Lines.Append(FloatToStr(RoundF(f, 2)));
  38.   Memo1.Lines.Append('');
  39.   f := -1213.245;
  40.   Memo1.Lines.Append(floattostr(f));
  41.   Memo1.Lines.Append(FloatToStr(RoundF(-1213.245, 2)));
  42.   Memo1.Lines.Append(FloatToStr(RoundF(f, 2)));
  43. end;

  44. end.
複製代碼
執行結果
四捨五入測試.png
‹ 上一主題|下一主題

Archiver|怕失憶論壇

GMT+8, 2024-4-23 18:39 , Processed in 0.026558 second(s), 12 queries .

Powered by Discuz! X1.5

© 2001-2010 Comsenz Inc.