{ ----------------------------------- 汎用共通処理関数ユニット 2004/08/18 ・作成 ・RoundOFF関数などを実装 ・CeilEx/FloorExも実装 2004/10/02 ・RandomRangeExを実装 //----------------------------------- } unit MathUnit; interface uses Math, XPtest; function RoundOff(X: Extended): Int64; function RoundOffEx(const X: Extended; DigitNumber: Integer): Extended; function IsSame(A, B: Extended; e: Extended=0): Boolean; procedure testRoundOff; function CeilEx(const X: Extended; DigitNumber: Integer): Extended; procedure testCeil; function FloorEx(const X: Extended; DigitNumber: Integer): Extended; overload; procedure testFloor; function RandomRangeEx(const AFrom, ATo: Extended; Digit: Byte): Extended; implementation {------------------------------- // HELPにのっているRoundOff 備考: 履歴: 2004/08/18 LongintからInt64に変更した //------------------------------} function RoundOff(X: Extended): Int64; begin if x >= 0 then Result := Trunc(x + 0.5) else Result := Trunc(x - 0.5); end; //------------------------------ {------------------------------- // RoundOffEx 機能: 任意の桁で四捨五入します。 引数説明: X: 四捨五入対象 DigitNumber: 桁数 3:100の桁 2:10の桁 1:一桁目 0:処理しない -1:少数点第一位(通常のRoundOffと同じ処理) -2:少数点第二位 -3:少数点第三位 戻り値: 四捨五入後のX 処理できない場合Xの値そのままが入るはず 備考: 履歴: 2001/09/04 //------------------------------} function RoundOffEx(const X: Extended; DigitNumber: Integer): Extended; var CalcDigit: Extended; begin Result := X; if X = 0 then Exit; case DigitNumber of 0: Exit; 1..High(DigitNumber): begin CalcDigit := IntPower(10, DigitNumber); Result := Roundoff(X / CalcDigit) * CalcDigit; end; Low(DigitNumber)..-1: begin CalcDigit := IntPower(10, Abs(DigitNumber)-1); Result := Roundoff(X * CalcDigit) / CalcDigit; end; end; end; //------------------------------ {------------------------------- // IsSame 機能: 適当に小さい誤差の範囲内で 浮動小数点値が等しいかどうかを調べる関数 引数説明: A, B: 比較対照 e: ±の誤差 戻り値: true:等しい false:等しくない 備考: 履歴: 2001/09/05 //------------------------------} function IsSame(A, B: Extended; e: Extended=0): Boolean; begin Result := Abs(A-B) <= e; end; //------------------------------ procedure testRoundOff; begin Check(True, IsSame(150, RoundOffEx(145, 1),0.000001)); Check(True, IsSame(150, RoundOffEx(154, 1),0.000001)); Check(True, IsSame(140, RoundOffEx(144, 1),0.000001)); Check(True, IsSame(160, RoundOffEx(155, 1),0.000001)); Check(True, IsSame(150, RoundOffEx(150, 1),0.000001)); Check(True, IsSame( 10, RoundOffEx( 14, 1),0.000001)); Check(True, IsSame( 10, RoundOffEx( 5, 1),0.000001)); Check(True, IsSame( 0, RoundOffEx( 4, 1),0.000001)); Check(True, IsSame( 20, RoundOffEx( 15, 1),0.000001)); Check(True, IsSame( 10, RoundOffEx( 10, 1),0.000001)); Check(True, IsSame(200, RoundOffEx(150, 2),0.000001)); Check(True, IsSame(100, RoundOffEx(140, 2),0.000001)); Check(True, IsSame(100, RoundOffEx(149, 2),0.000001)); Check(True, IsSame(200, RoundOffEx(249, 2),0.000001)); Check(True, IsSame(100, RoundOffEx( 50, 2),0.000001)); Check(True, IsSame(1000, RoundOffEx(1400, 3),0.000001)); Check(True, IsSame(2000, RoundOffEx(1500, 3),0.000001)); Check(True, IsSame(2000, RoundOffEx(1600, 3),0.000001)); Check(True, IsSame(1000, RoundOffEx(1499, 3),0.000001)); Check(True, IsSame(2000, RoundOffEx(2480, 3),0.000001)); Check(True, IsSame(-150, RoundOffEx(-145, 1),0.000001)); Check(True, IsSame(-150, RoundOffEx(-154, 1),0.000001)); Check(True, IsSame(-140, RoundOffEx(-144, 1),0.000001)); Check(True, IsSame(-160, RoundOffEx(-155, 1),0.000001)); Check(True, IsSame(-150, RoundOffEx(-150, 1),0.000001)); Check(True, IsSame(- 10, RoundOffEx( -14, 1),0.000001)); Check(True, IsSame(- 10, RoundOffEx( -5, 1),0.000001)); Check(True, IsSame(- 0, RoundOffEx( -4, 1),0.000001)); Check(True, IsSame(- 20, RoundOffEx( -15, 1),0.000001)); Check(True, IsSame(- 10, RoundOffEx( -10, 1),0.000001)); Check(True, IsSame(-200, RoundOffEx(-150, 2),0.000001)); Check(True, IsSame(-100, RoundOffEx(-140, 2),0.000001)); Check(True, IsSame(-100, RoundOffEx(-149, 2),0.000001)); Check(True, IsSame(-200, RoundOffEx(-249, 2),0.000001)); Check(True, IsSame(-100, RoundOffEx( -50, 2),0.000001)); Check(True, IsSame(-1000, RoundOffEx(-1400, 3),0.000001)); Check(True, IsSame(-2000, RoundOffEx(-1500, 3),0.000001)); Check(True, IsSame(-2000, RoundOffEx(-1600, 3),0.000001)); Check(True, IsSame(-1000, RoundOffEx(-1499, 3),0.000001)); Check(True, IsSame(-2000, RoundOffEx(-2480, 3),0.000001)); Check(True, IsSame(0, RoundOffEx(0.49, -1),0.000001)); Check(True, IsSame(1, RoundOffEx(0.50, -1),0.000001)); Check(True, IsSame(1, RoundOffEx(1.49, -1),0.000001)); Check(True, IsSame(2, RoundOffEx(1.50, -1),0.000001)); Check(True, IsSame(1.0, RoundOffEx(1.04, -2),0.000001)); Check(TRue, IsSame(1.1, RoundOffEx(1.05, -2),0.000001)); Check(True, IsSame(1.0001, RoundOffEx(1.00005000, -5),0.00000001)); Check(True, IsSame(1.0000, RoundOffEx(1.00004999, -5),0.000001)); Check(True, IsSame(1.000050, RoundOffEx(1.00005000, -6),0.000001)); Check(True, IsSame(1.000050, RoundOffEx(1.00004999, -6),0.000001)); Check(True, IsSame(1.000040, RoundOffEx(1.00004499, -6),0.000001)); Check(True, IsSame(-0, RoundOffEx(-0.49, -1),0.000001)); Check(True, IsSame(-1, RoundOffEx(-0.50, -1),0.000001)); Check(True, IsSame(-1, RoundOffEx(-1.49, -1),0.000001)); Check(True, IsSame(-2, RoundOffEx(-1.50, -1),0.000001)); Check(True, IsSame(-1.0, RoundOffEx(-1.04, -2),0.000001)); Check(TRue, IsSame(-1.1, RoundOffEx(-1.05, -2),0.000001)); Check(True, IsSame(-1.0001, RoundOffEx(-1.00005000, -5),0.00000001)); Check(True, IsSame(-1.0000, RoundOffEx(-1.00004999, -5),0.000001)); Check(True, IsSame(-1.000050, RoundOffEx(-1.00005000, -6),0.000001)); Check(True, IsSame(-1.000050, RoundOffEx(-1.00004999, -6),0.000001)); Check(True, IsSame(-1.000040, RoundOffEx(-1.00004499, -6),0.000001)); end; {------------------------------- // CeilEx/FloorEx 機能: 任意の桁で切り上げ/切り下げします 切り上げは正の絶対値方向、切り下げは負の無限大方向に 行われるので、負の値の場合動作に気をつけること。 引数説明: X: 計算対象 DigitNumber: 桁数 3:100の桁 2:10の桁 1:一桁目 0:処理しない -1:少数点第一位(通常のRoundOffと同じ処理) -2:少数点第二位 -3:少数点第三位 戻り値: 計算後のX 処理できない場合Xの値そのままが入る 備考: 履歴: 2004/08/18 //------------------------------} function CeilEx(const X: Extended; DigitNumber: Integer): Extended; var CalcDigit: Extended; begin Result := X; if X = 0 then Exit; case DigitNumber of 0: Exit; 1..High(DigitNumber): begin CalcDigit := IntPower(10, DigitNumber); Result := Math.Ceil(X / CalcDigit) * CalcDigit; end; Low(DigitNumber)..-1: begin CalcDigit := IntPower(10, Abs(DigitNumber)-1); Result := Math.Ceil(X * CalcDigit) / CalcDigit; end; end; end; procedure testCeil; begin Check(True, IsSame(150, CeilEx(145, 1),0.000001)); Check(True, IsSame(160, CeilEx(154, 1),0.000001)); Check(True, IsSame(150, CeilEx(144, 1),0.000001)); Check(True, IsSame(160, CeilEx(155, 1),0.000001)); Check(True, IsSame(150, CeilEx(150, 1),0.000001)); Check(True, IsSame( 20, CeilEx( 14, 1),0.000001)); Check(True, IsSame( 10, CeilEx( 5, 1),0.000001)); Check(True, IsSame( 10, CeilEx( 4, 1),0.000001)); Check(True, IsSame( 20, CeilEx( 15, 1),0.000001)); Check(True, IsSame( 10, CeilEx( 10, 1),0.000001)); Check(True, IsSame(200, CeilEx(150, 2),0.000001)); Check(True, IsSame(200, CeilEx(140, 2),0.000001)); Check(True, IsSame(200, CeilEx(149, 2),0.000001)); Check(True, IsSame(300, CeilEx(249, 2),0.000001)); Check(True, IsSame(100, CeilEx( 50, 2),0.000001)); Check(True, IsSame(2000, CeilEx(1400, 3),0.000001)); Check(True, IsSame(2000, CeilEx(1500, 3),0.000001)); Check(True, IsSame(2000, CeilEx(1600, 3),0.000001)); Check(True, IsSame(2000, CeilEx(1499, 3),0.000001)); Check(True, IsSame(3000, CeilEx(2480, 3),0.000001)); Check(True, IsSame(-140, CeilEx(-145, 1),0.000001)); Check(True, IsSame(-150, CeilEx(-154, 1),0.000001)); Check(True, IsSame(-140, CeilEx(-144, 1),0.000001)); Check(True, IsSame(-150, CeilEx(-155, 1),0.000001)); Check(True, IsSame(-150, CeilEx(-150, 1),0.000001)); Check(True, IsSame(- 10, CeilEx( -14, 1),0.000001)); Check(True, IsSame( 0, CeilEx( -5, 1),0.000001)); Check(True, IsSame( 0, CeilEx( -4, 1),0.000001)); Check(True, IsSame(- 10, CeilEx( -15, 1),0.000001)); Check(True, IsSame(- 10, CeilEx( -10, 1),0.000001)); Check(True, IsSame(-100, CeilEx(-150, 2),0.000001)); Check(True, IsSame(-100, CeilEx(-140, 2),0.000001)); Check(True, IsSame(-100, CeilEx(-149, 2),0.000001)); Check(True, IsSame(-200, CeilEx(-249, 2),0.000001)); Check(True, IsSame( 0, CeilEx( -50, 2),0.000001)); Check(True, IsSame(-1000, CeilEx(-1400, 3),0.000001)); Check(True, IsSame(-1000, CeilEx(-1500, 3),0.000001)); Check(True, IsSame(-1000, CeilEx(-1600, 3),0.000001)); Check(True, IsSame(-1000, CeilEx(-1499, 3),0.000001)); Check(True, IsSame(-2000, CeilEx(-2480, 3),0.000001)); Check(True, IsSame(1, CeilEx(0.49, -1),0.000001)); Check(True, IsSame(1, CeilEx(0.50, -1),0.000001)); Check(True, IsSame(2, CeilEx(1.49, -1),0.000001)); Check(True, IsSame(2, CeilEx(1.50, -1),0.000001)); Check(True, IsSame(1.1, CeilEx(1.04, -2),0.000001)); Check(TRue, IsSame(1.1, CeilEx(1.05, -2),0.000001)); Check(True, IsSame(1.0001, CeilEx(1.00005000, -5),0.00000001)); Check(True, IsSame(1.0001, CeilEx(1.00004999, -5),0.000001)); Check(True, IsSame(1.000050, CeilEx(1.00005000, -6),0.000001)); Check(True, IsSame(1.000050, CeilEx(1.00004999, -6),0.000001)); Check(True, IsSame(1.000050, CeilEx(1.00004499, -6),0.000001)); Check(True, IsSame(-0, CeilEx(-0.49, -1),0.000001)); Check(True, IsSame(-0, CeilEx(-0.50, -1),0.000001)); Check(True, IsSame(-1, CeilEx(-1.49, -1),0.000001)); Check(True, IsSame(-1, CeilEx(-1.50, -1),0.000001)); Check(True, IsSame(-1.0, CeilEx(-1.04, -2),0.000001)); Check(TRue, IsSame(-1.0, CeilEx(-1.05, -2),0.000001)); Check(True, IsSame(-1.0000, CeilEx(-1.00005000, -5),0.00000001)); Check(True, IsSame(-1.0000, CeilEx(-1.00004999, -5),0.000001)); Check(True, IsSame(-1.000050, CeilEx(-1.00005000, -6),0.000001)); Check(True, IsSame(-1.000040, CeilEx(-1.00004999, -6),0.000001)); Check(True, IsSame(-1.000040, CeilEx(-1.00004499, -6),0.000001)); end; function FloorEx(const X: Extended; DigitNumber: Integer): Extended; overload; var CalcDigit: Extended; begin Result := X; if X = 0 then Exit; case DigitNumber of 0: Exit; 1..High(DigitNumber): begin CalcDigit := IntPower(10, DigitNumber); Result := Math.Floor(X / CalcDigit) * CalcDigit; end; Low(DigitNumber)..-1: begin CalcDigit := IntPower(10, Abs(DigitNumber)-1); Result := Math.Floor(X * CalcDigit) / CalcDigit; end; end; end; procedure testFloor; begin Check(True, IsSame(140, FloorEx(145, 1),0.000001)); Check(True, IsSame(150, FloorEx(154, 1),0.000001)); Check(True, IsSame(140, FloorEx(144, 1),0.000001)); Check(True, IsSame(150, FloorEx(155, 1),0.000001)); Check(True, IsSame(150, FloorEx(150, 1),0.000001)); Check(True, IsSame( 10, FloorEx( 14, 1),0.000001)); Check(True, IsSame( 0, FloorEx( 5, 1),0.000001)); Check(True, IsSame( 0, FloorEx( 4, 1),0.000001)); Check(True, IsSame( 10, FloorEx( 15, 1),0.000001)); Check(True, IsSame( 10, FloorEx( 10, 1),0.000001)); Check(True, IsSame(100, FloorEx(150, 2),0.000001)); Check(True, IsSame(100, FloorEx(140, 2),0.000001)); Check(True, IsSame(100, FloorEx(149, 2),0.000001)); Check(True, IsSame(200, FloorEx(249, 2),0.000001)); Check(True, IsSame( 0, FloorEx( 50, 2),0.000001)); Check(True, IsSame(1000, FloorEx(1400, 3),0.000001)); Check(True, IsSame(1000, FloorEx(1500, 3),0.000001)); Check(True, IsSame(1000, FloorEx(1600, 3),0.000001)); Check(True, IsSame(1000, FloorEx(1499, 3),0.000001)); Check(True, IsSame(2000, FloorEx(2480, 3),0.000001)); Check(True, IsSame(-150, FloorEx(-145, 1),0.000001)); Check(True, IsSame(-160, FloorEx(-154, 1),0.000001)); Check(True, IsSame(-150, FloorEx(-144, 1),0.000001)); Check(True, IsSame(-160, FloorEx(-155, 1),0.000001)); Check(True, IsSame(-150, FloorEx(-150, 1),0.000001)); Check(True, IsSame(- 20, FloorEx( -14, 1),0.000001)); Check(True, IsSame(- 10, FloorEx( -5, 1),0.000001)); Check(True, IsSame(- 10, FloorEx( -4, 1),0.000001)); Check(True, IsSame(- 20, FloorEx( -15, 1),0.000001)); Check(True, IsSame(- 10, FloorEx( -10, 1),0.000001)); Check(True, IsSame(-200, FloorEx(-150, 2),0.000001)); Check(True, IsSame(-200, FloorEx(-140, 2),0.000001)); Check(True, IsSame(-200, FloorEx(-149, 2),0.000001)); Check(True, IsSame(-300, FloorEx(-249, 2),0.000001)); Check(True, IsSame(-100, FloorEx( -50, 2),0.000001)); Check(True, IsSame(-2000, FloorEx(-1400, 3),0.000001)); Check(True, IsSame(-2000, FloorEx(-1500, 3),0.000001)); Check(True, IsSame(-2000, FloorEx(-1600, 3),0.000001)); Check(True, IsSame(-2000, FloorEx(-1499, 3),0.000001)); Check(True, IsSame(-3000, FloorEx(-2480, 3),0.000001)); Check(True, IsSame(0, FloorEx(0.49, -1),0.000001)); Check(True, IsSame(0, FloorEx(0.50, -1),0.000001)); Check(True, IsSame(1, FloorEx(1.49, -1),0.000001)); Check(True, IsSame(1, FloorEx(1.50, -1),0.000001)); Check(True, IsSame(1.0, FloorEx(1.04, -2),0.000001)); Check(TRue, IsSame(1.0, FloorEx(1.05, -2),0.000001)); Check(True, IsSame(1.0000, FloorEx(1.00005000, -5),0.00000001)); Check(True, IsSame(1.0000, FloorEx(1.00004999, -5),0.000001)); Check(True, IsSame(1.000050, FloorEx(1.00005000, -6),0.000001)); Check(True, IsSame(1.000040, FloorEx(1.00004999, -6),0.000001)); Check(True, IsSame(1.000040, FloorEx(1.00004499, -6),0.000001)); Check(True, IsSame(-1, FloorEx(-0.49, -1),0.000001)); Check(True, IsSame(-1, FloorEx(-0.50, -1),0.000001)); Check(True, IsSame(-2, FloorEx(-1.49, -1),0.000001)); Check(True, IsSame(-2, FloorEx(-1.50, -1),0.000001)); Check(True, IsSame(-1.1, FloorEx(-1.04, -2),0.000001)); Check(TRue, IsSame(-1.1, FloorEx(-1.05, -2),0.000001)); Check(True, IsSame(-1.0001, FloorEx(-1.00005000, -5),0.00000001)); Check(True, IsSame(-1.0001, FloorEx(-1.00004999, -5),0.000001)); Check(True, IsSame(-1.000050, FloorEx(-1.00005000, -6),0.000001)); Check(True, IsSame(-1.000050, FloorEx(-1.00004999, -6),0.000001)); Check(True, IsSame(-1.000050, FloorEx(-1.00004499, -6),0.000001)); end; {------------------------------- // RandomRangeEx 機能: 任意桁の範囲でRandomRangeする関数 引数説明: AFrom/ATo: 範囲 Digit: 桁数 1:小数点1桁 2:小数点2桁 3:小数点3桁 0:処理しない 戻り値: AFrom/AToで示される範囲の乱数 備考: 履歴: 2004/10/02 //------------------------------} function RandomRangeEx(const AFrom, ATo: Extended; Digit: Byte): Extended; var CalcDigit: Extended; begin CalcDigit := IntPower(10, Digit); // Result := RandomRange(RoundOff(AFrom*CalcDigit), RoundOff(ATo*CalcDigit)) / CalcDigit; end; //------------------------------ end.