diff --git a/build.vc11/mpir.net/mpir.net-tests/mpir.net-tests.csproj b/build.vc11/mpir.net/mpir.net-tests/mpir.net-tests.csproj index fea31899..2fe2c95c 100644 --- a/build.vc11/mpir.net/mpir.net-tests/mpir.net-tests.csproj +++ b/build.vc11/mpir.net/mpir.net-tests/mpir.net-tests.csproj @@ -106,6 +106,9 @@ HugeFloatTests\ConstructionAndDisposal.cs + + HugeFloatTests\Conversions.cs + HugeIntTests\Arithmetic.cs diff --git a/mpir.net/mpir.net-tests/HugeFloatTests/ConstructionAndDisposal.cs b/mpir.net/mpir.net-tests/HugeFloatTests/ConstructionAndDisposal.cs index 8cf8df43..981da817 100644 --- a/mpir.net/mpir.net-tests/HugeFloatTests/ConstructionAndDisposal.cs +++ b/mpir.net/mpir.net-tests/HugeFloatTests/ConstructionAndDisposal.cs @@ -58,7 +58,7 @@ namespace MPIR.Tests.HugeFloatTests Assert.AreEqual(128UL, a._allocatedPrecision); Assert.AreEqual(128UL, a.Precision); Assert.AreEqual(1, a.Exponent()); - Assert.AreEqual("0." + n.ToString("X") + "@16", a.ToString(16)); + Assert.AreEqual("0." + n.ToString("X") + "@16", a.ToString(16, false, true)); } } @@ -71,7 +71,7 @@ namespace MPIR.Tests.HugeFloatTests Assert.AreEqual(128UL, a._allocatedPrecision); Assert.AreEqual(128UL, a.Precision); Assert.AreEqual(1, a.Exponent()); - Assert.AreEqual("-0." + n.ToString("X") + "@16", a.ToString(16)); + Assert.AreEqual("-0." + n.ToString("X") + "@16", a.ToString(16, false, true)); } } @@ -84,7 +84,7 @@ namespace MPIR.Tests.HugeFloatTests Assert.AreEqual(128UL, a._allocatedPrecision); Assert.AreEqual(128UL, a.Precision); Assert.AreEqual(1, a.Exponent()); - Assert.AreEqual("0." + n.ToString("X") + "@16", a.ToString(16)); + Assert.AreEqual("0." + n.ToString("X") + "@16", a.ToString(16, false, true)); } } @@ -140,7 +140,7 @@ namespace MPIR.Tests.HugeFloatTests var n = "143210ABCDEF32123457ACDB324.59879"; using (var a = new HugeFloat(n, 16)) { - Assert.AreEqual("0.143210ABCDEF32123457ACDB32459879@27", a.ToString(16)); + Assert.AreEqual("0.143210ABCDEF32123457ACDB32459879@27", a.ToString(16, false, true)); } } diff --git a/mpir.net/mpir.net-tests/HugeFloatTests/Conversions.cs b/mpir.net/mpir.net-tests/HugeFloatTests/Conversions.cs index 02aadec3..e31ef6b6 100644 --- a/mpir.net/mpir.net-tests/HugeFloatTests/Conversions.cs +++ b/mpir.net/mpir.net-tests/HugeFloatTests/Conversions.cs @@ -21,70 +21,61 @@ using System; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace MPIR.Tests.HugeRationalTests +namespace MPIR.Tests.HugeFloatTests { [TestClass] public class Conversions { [TestMethod] - public void RationalToStringDecimal() + public void FloatToStringDecimal() { - var n = "-23429384756298357462983476598345623984756"; - var d = "115756986668303657898962467957"; - var s = n + "/" + d; - using (var a = new HugeRational(s)) + var n = "-234293847562.98357462983476598345623984756"; + using (var a = new HugeFloat(n)) { - Assert.AreEqual(s, a.ToString()); + FloatAssert.AreEqual(n, a); } } [TestMethod] - public void RationalToStringHex() + public void FloatToStringHex() { - var n = "-23429abcdef298357462983fedcba345623984756"; - var d = "17607ef654eb9a13ffa163c75"; - var s = n + "/" + d; - using (var a = new HugeRational(s, 16)) + var s = "-23429abcdef29835746298.3fedcba34562"; + using (var a = new HugeFloat(s, 16)) { - Assert.AreEqual(s, a.ToString(16, true)); - Assert.AreEqual(s.ToUpper(), a.ToString(16)); + Assert.AreEqual("-0.23429abcdef298357462983fedcba34562@16", a.ToString(16, true)); + Assert.AreEqual("-0.23429ABCDEF298357462983FEDCBA34562@16", a.ToString(16)); + + Assert.AreEqual("-0.23429abcdef298357462983fedcba34562@22", a.ToString(16, true, true)); + Assert.AreEqual("-0.23429ABCDEF298357462983FEDCBA34562@22", a.ToString(16, false, true)); } } [TestMethod] - public void RationalFromUlong() + public void FloatFromUlong() { - using (var a = new HugeRational()) + using (var a = new HugeFloat()) { ulong b = 0xF84739ABCDEF4876; - ulong d = 12764787846358441471; - a.SetTo(b, d); - Assert.AreEqual(b.ToString() + "/" + d.ToString(), a.ToString()); - a.SetTo(b); - Assert.AreEqual(b.ToString() + "/1", a.ToString()); + FloatAssert.AreEqual(b + ".", a); } } [TestMethod] - public void RationalFromLong() + public void FloatFromLong() { - using (var a = new HugeRational()) + using (var a = new HugeFloat()) { long b = -0x784739ABCDEF4876; - ulong d = 12764787846358441471; - a.SetTo(b, d); - Assert.AreEqual(b.ToString() + "/" + d.ToString(), a.ToString()); - a.SetTo(b); - Assert.AreEqual(b.ToString() + "/1", a.ToString()); + FloatAssert.AreEqual(b + ".", a); } } [TestMethod] - public void RationalToAndFromDouble() + public void FloatToAndFromDouble() { - using (var a = new HugeRational()) + using (var a = new HugeFloat()) { a.SetTo(-123.25); @@ -95,9 +86,9 @@ namespace MPIR.Tests.HugeRationalTests } [TestMethod] - public void RationalToAndFromFloat() + public void FloatToAndFromFloat() { - using (var a = new HugeRational()) + using (var a = new HugeFloat()) { a.SetTo(-123.125f); @@ -109,78 +100,40 @@ namespace MPIR.Tests.HugeRationalTests } [TestMethod] - public void RationalFromString() + public void FloatFromString() { - using (var a = new HugeRational()) + using (var a = new HugeFloat()) { - var n = "98762934876529834765234123984761/115756986668303657898962467957"; + var n = "98762934876529834765234123.984761"; a.SetTo(n); - Assert.AreEqual(n, a.ToString()); - - n = "-98ABCDEF876529834765234123984761/17607EF654EB9A13FFA163C75"; - a.SetTo(n, 16); - Assert.AreEqual(n, a.ToString(16)); - - n = "-98ABCDEF876529834765234123984761"; - a.SetTo(n, 16); - Assert.AreEqual(n + "/1", a.ToString(16)); + FloatAssert.AreEqual(n, a); } } [TestMethod] [ExpectedException(typeof(ArgumentException))] - public void RationalFromInvalidString() + public void FloatFromInvalidString() { - using (var a = new HugeRational()) + using (var a = new HugeFloat()) { a.SetTo("12345A"); } } [TestMethod] - [ExpectedException(typeof(ArgumentException))] - public void RationalFromInvalidString2() - { - using (var a = new HugeRational()) - { - a.SetTo("12345/13345A"); - } - } - - [TestMethod] - public void RationalToStringTruncated() + public void FloatToStringTruncated() { using (var d = new HugeInt("115756986668303657898962467957")) using (var e = new HugeInt(d ^ 10)) { var s = e.ToString(10); - var n = string.Concat("123456789".Select(c => new string(c, 30))); - using (var a = new HugeRational(n + "/" + s)) + using (var a = HugeFloat.Allocate(1200)) { - Assert.AreEqual(n + "/" + s, a.ToString(10)); - Assert.AreEqual("..." + n.Substring(n.Length - 256) + "/..." + s.Substring(s.Length - 256), a.ToString()); - a.Value = -a; - Assert.AreEqual("-..." + n.Substring(n.Length - 256) + "/..." + s.Substring(s.Length - 256), a.ToString()); + a.SetTo(s); + Assert.AreEqual(256, a.ToString().Replace("0.", "").Replace("@291", "").Length); + Assert.AreEqual(291, a.ToString(10).Replace("0.", "").Replace("@291", "").Length); } } } - - [TestMethod] - public void RationalApproximateSizeInBase() - { - using (var a = new HugeRational("2983475029834750293429834750298347502934298347502983475029342983475029834750293429834750298347502934/115756986668303657898962467957")) - { - AssertBetween(131, 133, a.ApproximateSizeInBase(10)); - AssertBetween(429, 429, a.ApproximateSizeInBase(2)); - AssertBetween(109, 109, a.ApproximateSizeInBase(16)); - AssertBetween(84, 86, a.ApproximateSizeInBase(36)); - AssertBetween(74, 76, a.ApproximateSizeInBase(62)); - } - } - - private void AssertBetween(int min, int max, long actual) - { - Assert.IsTrue(actual >= min && actual <= max, "Expected {0} to {1}, actual {2}", min, max, actual); - } } } diff --git a/mpir.net/mpir.net/HugeFloat.cpp b/mpir.net/mpir.net/HugeFloat.cpp index d32c7ccf..4f6e67ea 100644 --- a/mpir.net/mpir.net/HugeFloat.cpp +++ b/mpir.net/mpir.net/HugeFloat.cpp @@ -123,7 +123,7 @@ namespace MPIR #pragma region object overrides - String^ MPTYPE::ToString(int base, bool lowercase, int maxDigits) + String^ MPTYPE::ToString(int base, bool lowercase, int maxDigits, bool exponentInDecimal) { if(base < 2 || base > 62) throw gcnew ArgumentOutOfRangeException("base", "Invalid base"); @@ -153,7 +153,16 @@ namespace MPIR str++; } result->Append((wchar_t)'@'); - result->Append(exponent); + + if(exponentInDecimal) + { + result->Append(exponent); + } + else + { + HugeInt exp((mpir_si) exponent); + result->Append(exp.ToString(base, lowercase)); + } } (*__gmp_free_func)(allocatedStr, allocated); diff --git a/mpir.net/mpir.net/HugeFloat.h b/mpir.net/mpir.net/HugeFloat.h index c8480b33..8179c3a0 100644 --- a/mpir.net/mpir.net/HugeFloat.h +++ b/mpir.net/mpir.net/HugeFloat.h @@ -763,7 +763,7 @@ namespace MPIR } void FromString(String^ value, int base); MPTYPE(bool initialize); - String^ ToString(int base, bool lowercase, int maxDigits); + String^ ToString(int base, bool lowercase, int maxDigits, bool exponentInDecimal); internal: virtual void DeallocateStruct() @@ -896,7 +896,7 @@ namespace MPIR /// Setting MpirSettings.ToStringDigits to 0 removes the upper limit. /// /// A string representation of the number in decimal, possibly cut off if the number has more digits than MpirSettings.ToStringDigits. - virtual String^ ToString() override { return ToString(10, false, MpirSettings::ToStringDigits); } + virtual String^ ToString() override { return ToString(10, false, MpirSettings::ToStringDigits, false); } /// /// Converts the number to a string in the specified base. @@ -904,7 +904,7 @@ namespace MPIR /// /// The base to use for the output. The base can be from 2 to 62; uppercase letters represent digits 10-35 and lowercase letters represent digits 36-61. /// A string representation of the number in the specified base. - String^ ToString(int base) { return ToString(base, false, 0); } + String^ ToString(int base) { return ToString(base, false, 0, false); } /// /// Converts the number to a string in the specified base. @@ -916,7 +916,20 @@ namespace MPIR /// Indicates if lowercase or uppercase letters should be used for the output. /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. /// A string representation of the number in the specified base. - String^ ToString(int base, bool lowercase) { return ToString(base, lowercase, 0); } + String^ ToString(int base, bool lowercase) { return ToString(base, lowercase, 0, false); } + + /// + /// Converts the number to a string in the specified base. + /// This method always produces the complete output regardless of the MpirSettings.ToStringDigits setting. + /// + /// The base to use for the output. + /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. + /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// Indicates if lowercase or uppercase letters should be used for the output. + /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. + /// True to always show the exponent in decimal, False to use the same base as the mantissa + /// A string representation of the number in the specified base. + String^ ToString(int base, bool lowercase, bool exponentInDecimal) { return ToString(base, lowercase, 0, exponentInDecimal); } ///// ///// Returns the absolute value of the number as a ulong.