From b4a3c7cc45c5fb36465c44979a0832aa8c746608 Mon Sep 17 00:00:00 2001 From: Westermann Date: Sat, 2 Feb 2019 16:13:27 +0100 Subject: [PATCH] Added class method Math.Round(a : Double; digits : Integer) : Double; Added Test. fixed Convert.TrimLeadingZeros in case of only the last char <> "0" it retuned the whole inputvalue Added Test --- Source/Convert.pas | 4 +-- Source/Math.pas | 73 ++++++++++++++++++++++++++++++++++++---------- Test/Convert.pas | 32 ++++++++++++++++++++ Test/Math.pas | 41 ++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 17 deletions(-) create mode 100644 Test/Math.pas diff --git a/Source/Convert.pas b/Source/Convert.pas index a3c02ca..037b9f1 100644 --- a/Source/Convert.pas +++ b/Source/Convert.pas @@ -287,9 +287,9 @@ implementation method Convert.TrimLeadingZeros(aValue: not nullable String): not nullable String; begin - for i: Int32 := 0 to length(aValue)-2 do + for i: Int32 := 0 to length(aValue)-1 do if aValue[i] ≠ '0' then exit aValue.Substring(i); - exit aValue; + exit ""; end; method Convert.ToHexString(aValue: UInt64; aWidth: Integer := 0): not nullable String; diff --git a/Source/Math.pas b/Source/Math.pas index 9551ebe..5b9ab37 100644 --- a/Source/Math.pas +++ b/Source/Math.pas @@ -37,6 +37,7 @@ interface class method Min(a,b: Int64): Int64; mapped to min(a,b); class method Pow(x, y: Double): Double; class method Round(a: Double): Int64; + class method Round(a : Double; digits : Integer) : Double; class method Sign(d: Double): Integer; class method Sin(d: Double): Double; mapped to sin(d); class method Sinh(d: Double): Double; mapped to sinh(d); @@ -72,6 +73,7 @@ interface class method Min(a,b: Int64): Int64; class method Pow(x, y: Double): Double; class method Round(a: Double): Int64; + class method Round(a : Double; digits : Integer) : Double; class method Sign(d: Double): Integer; class method Sin(x: Double): Double; class method Sinh(x: Double): Double; @@ -106,6 +108,7 @@ interface class method Min(a,b: Int64): Int64; mapped to Min(a,b); class method Pow(x, y: Double): Double; mapped to Pow(x,y); class method Round(a: Double): Int64; + class method Round(a : Double; digits : Integer) : Double; class method Sign(d: Double): Integer; mapped to Sign(d); class method Sin(d: Double): Double; mapped to Sin(d); class method Sinh(d: Double): Double; mapped to Sinh(d); @@ -238,25 +241,19 @@ implementation exit Int64(Floor(a + 0.499999999999999999)); end; -{$ELSEIF TOFFEE} -class method Math.Round(a: Double): Int64; -begin - if Consts.IsNaN(a) or Consts.IsInfinity(a) then - raise new ArgumentException("Value can not be rounded to Int64"); - exit Int64(Floor(a + 0.499999999999999999)); -end; -{$ELSEIF ECHOES or ISLAND} -class method Math.Round(a: Double): Int64; +class method Math.Round(a : Double; digits : Integer) : Double; begin - if Consts.IsNaN(a) or Consts.IsInfinity(a) then - raise new ArgumentException("Value can not be rounded to Int64"); - - exit Int64(Floor(a + 0.499999999999999999)); + if (digits < 0) or (digits > 15) then + raise new ArgumentException("digits must be between 0 and 15"); + var factor := Pow(10.0, -digits); + if a > 0 then + result := Truncate((a / factor)+0.5) * factor + else + result := Truncate((a / factor)-0.5) * factor end; -{$ENDIF} -{$IF COOPER} + class method Math.Sign(d: Double): Integer; begin if Consts.IsNaN(d) then @@ -266,6 +263,7 @@ implementation if d < 0 then exit -1; exit 0; end; + {$ELSEIF TOFFEE} class method Math.Sign(d: Double): Integer; begin @@ -434,6 +432,51 @@ implementation begin exit iif(a < b, a, b); end; + +class method Math.Round(a: Double): Int64; +begin + if Consts.IsNaN(a) or Consts.IsInfinity(a) then + raise new ArgumentException("Value can not be rounded to Int64"); + + exit Int64(Floor(a + 0.499999999999999999)); +end; + +class method Math.Round(a : Double; digits : Integer) : Double; +begin + if (digits < 0) or (digits > 15) then + raise new ArgumentException("digits must be between 0 and 15"); + var factor := Pow(10.0, -digits); + if a > 0 then + result := Truncate((a / factor)+0.5) * factor + else + result := Truncate((a / factor)-0.5) * factor +end; + + {$ELSEIF ECHOES OR ISLAND} +class method Math.Round(a: Double): Int64; +begin + if Consts.IsNaN(a) or Consts.IsInfinity(a) then + raise new ArgumentException("Value can not be rounded to Int64"); + + exit Int64(Floor(a + 0.499999999999999999)); +end; + +class method Math.Round(a : Double; digits : Integer) : Double; +begin + {$IF ECHOES} + result := mapped.Round(a, digits); + exit; + {$ELSE} + if (digits < 0) or (digits > 15) then + raise new ArgumentException("digits must be between 0 and 15"); + var factor := Pow(10.0, -digits); + if a > 0 then + result := Truncate((a / factor)+0.5) * factor + else + result := Truncate((a / factor)-0.5) * factor + {$ENDIF} +end; + {$ENDIF} end. \ No newline at end of file diff --git a/Test/Convert.pas b/Test/Convert.pas index 7cc61e1..c816437 100644 --- a/Test/Convert.pas +++ b/Test/Convert.pas @@ -8,6 +8,14 @@ ConvertTests = public class(Test) private protected + // Copy from Convert.... because in Convert it is private and inline + method internTrimLeadingZeros(aValue: not nullable String): not nullable String; + begin + for i: Int32 := 0 to length(aValue)-1 do + if aValue[i] ≠ '0' then exit aValue.Substring(i); + exit ""; + end; + public method TestInt32; @@ -68,6 +76,30 @@ //Assert.AreEqual(Convert.TryToInt32("9223372036854775807"), 9223372036854775807); // fails to compile: // E546 Value "9223372036854775807" exceeds the bounds of target type "Int32" end; + + method TestHex; + begin + Assert.AreEqual(Convert.ToHexString(10,0), "A"); + end; + + + + method TrimLeadingZeros; + begin + var res : String; + var aValue := "000000000000000A"; + res := internTrimLeadingZeros(aValue); + Assert.AreEqual(res, "A"); + aValue := "00000000000000A0B"; + res := internTrimLeadingZeros(aValue); + Assert.AreEqual(res, "A0B"); + + aValue := "0000000000000000"; + res := internTrimLeadingZeros(aValue); + Assert.AreEqual(res, ""); + + end; + end; end. \ No newline at end of file diff --git a/Test/Math.pas b/Test/Math.pas new file mode 100644 index 0000000..66352a7 --- /dev/null +++ b/Test/Math.pas @@ -0,0 +1,41 @@ +namespace Elements.RTL2.Tests.Shared; + +interface + +uses + RemObjects.Elements.RTL, + RemObjects.Elements.EUnit; + +type + MathTest = public class(Test) + private + protected + public + method RoundTest; + end; + +implementation + +method MathTest.RoundTest; +begin + // const PI: Double = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679; + var a : Double := 3.141592653589793;//2384626433832795028841971693993751058209749445923078164062862089986280348253421170679; + + Assert.DoesNotThrows(()-> Math.Round(a)); + Assert.AreEqual(Math.Round(a), 3); + + {$if ECHOES or TOFFEE or ISLAND or COOPER} + Assert.Throws(()-> Math.Round(a,-1)); + Assert.Throws(()-> Math.Round(a,16)); + Assert.AreEqual(Math.Round(a,0), 3.0); + Assert.AreEqual(Math.Round(a,4), 3.1416); + Assert.AreEqual(Math.Round(a,9), 3.141592654); + Assert.AreEqual(Math.Round(a,12), 3.141592653590); + Assert.AreEqual(Math.Round(a,13), 3.1415926535898); + Assert.AreEqual(Math.Round(a,14), 3.14159265358979); + Assert.AreEqual(Math.Round(a,15), 3.141592653589793); + {$ENDIF} + +end; + +end. \ No newline at end of file