Float conversion tests and full implementation of ToString()

This commit is contained in:
Alex Dyachenko 2014-06-17 17:53:26 -04:00
parent cc66a187e1
commit f971feae43
5 changed files with 69 additions and 91 deletions

View File

@ -106,6 +106,9 @@
<Compile Include="..\..\..\mpir.net\mpir.net-tests\HugeFloatTests\ConstructionAndDisposal.cs"> <Compile Include="..\..\..\mpir.net\mpir.net-tests\HugeFloatTests\ConstructionAndDisposal.cs">
<Link>HugeFloatTests\ConstructionAndDisposal.cs</Link> <Link>HugeFloatTests\ConstructionAndDisposal.cs</Link>
</Compile> </Compile>
<Compile Include="..\..\..\mpir.net\mpir.net-tests\HugeFloatTests\Conversions.cs">
<Link>HugeFloatTests\Conversions.cs</Link>
</Compile>
<Compile Include="..\..\..\mpir.net\mpir.net-tests\HugeIntTests\Arithmetic.cs"> <Compile Include="..\..\..\mpir.net\mpir.net-tests\HugeIntTests\Arithmetic.cs">
<Link>HugeIntTests\Arithmetic.cs</Link> <Link>HugeIntTests\Arithmetic.cs</Link>
</Compile> </Compile>

View File

@ -58,7 +58,7 @@ namespace MPIR.Tests.HugeFloatTests
Assert.AreEqual(128UL, a._allocatedPrecision); Assert.AreEqual(128UL, a._allocatedPrecision);
Assert.AreEqual(128UL, a.Precision); Assert.AreEqual(128UL, a.Precision);
Assert.AreEqual(1, a.Exponent()); 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._allocatedPrecision);
Assert.AreEqual(128UL, a.Precision); Assert.AreEqual(128UL, a.Precision);
Assert.AreEqual(1, a.Exponent()); 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._allocatedPrecision);
Assert.AreEqual(128UL, a.Precision); Assert.AreEqual(128UL, a.Precision);
Assert.AreEqual(1, a.Exponent()); 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"; var n = "143210ABCDEF32123457ACDB324.59879";
using (var a = new HugeFloat(n, 16)) 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));
} }
} }

View File

@ -21,70 +21,61 @@ using System;
using System.Linq; using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MPIR.Tests.HugeRationalTests namespace MPIR.Tests.HugeFloatTests
{ {
[TestClass] [TestClass]
public class Conversions public class Conversions
{ {
[TestMethod] [TestMethod]
public void RationalToStringDecimal() public void FloatToStringDecimal()
{ {
var n = "-23429384756298357462983476598345623984756"; var n = "-234293847562.98357462983476598345623984756";
var d = "115756986668303657898962467957"; using (var a = new HugeFloat(n))
var s = n + "/" + d;
using (var a = new HugeRational(s))
{ {
Assert.AreEqual(s, a.ToString()); FloatAssert.AreEqual(n, a);
} }
} }
[TestMethod] [TestMethod]
public void RationalToStringHex() public void FloatToStringHex()
{ {
var n = "-23429abcdef298357462983fedcba345623984756"; var s = "-23429abcdef29835746298.3fedcba34562";
var d = "17607ef654eb9a13ffa163c75"; using (var a = new HugeFloat(s, 16))
var s = n + "/" + d;
using (var a = new HugeRational(s, 16))
{ {
Assert.AreEqual(s, a.ToString(16, true)); Assert.AreEqual("-0.23429abcdef298357462983fedcba34562@16", a.ToString(16, true));
Assert.AreEqual(s.ToUpper(), a.ToString(16)); 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] [TestMethod]
public void RationalFromUlong() public void FloatFromUlong()
{ {
using (var a = new HugeRational()) using (var a = new HugeFloat())
{ {
ulong b = 0xF84739ABCDEF4876; ulong b = 0xF84739ABCDEF4876;
ulong d = 12764787846358441471;
a.SetTo(b, d);
Assert.AreEqual(b.ToString() + "/" + d.ToString(), a.ToString());
a.SetTo(b); a.SetTo(b);
Assert.AreEqual(b.ToString() + "/1", a.ToString()); FloatAssert.AreEqual(b + ".", a);
} }
} }
[TestMethod] [TestMethod]
public void RationalFromLong() public void FloatFromLong()
{ {
using (var a = new HugeRational()) using (var a = new HugeFloat())
{ {
long b = -0x784739ABCDEF4876; long b = -0x784739ABCDEF4876;
ulong d = 12764787846358441471;
a.SetTo(b, d);
Assert.AreEqual(b.ToString() + "/" + d.ToString(), a.ToString());
a.SetTo(b); a.SetTo(b);
Assert.AreEqual(b.ToString() + "/1", a.ToString()); FloatAssert.AreEqual(b + ".", a);
} }
} }
[TestMethod] [TestMethod]
public void RationalToAndFromDouble() public void FloatToAndFromDouble()
{ {
using (var a = new HugeRational()) using (var a = new HugeFloat())
{ {
a.SetTo(-123.25); a.SetTo(-123.25);
@ -95,9 +86,9 @@ namespace MPIR.Tests.HugeRationalTests
} }
[TestMethod] [TestMethod]
public void RationalToAndFromFloat() public void FloatToAndFromFloat()
{ {
using (var a = new HugeRational()) using (var a = new HugeFloat())
{ {
a.SetTo(-123.125f); a.SetTo(-123.125f);
@ -109,78 +100,40 @@ namespace MPIR.Tests.HugeRationalTests
} }
[TestMethod] [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); a.SetTo(n);
Assert.AreEqual(n, a.ToString()); FloatAssert.AreEqual(n, a);
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));
} }
} }
[TestMethod] [TestMethod]
[ExpectedException(typeof(ArgumentException))] [ExpectedException(typeof(ArgumentException))]
public void RationalFromInvalidString() public void FloatFromInvalidString()
{ {
using (var a = new HugeRational()) using (var a = new HugeFloat())
{ {
a.SetTo("12345A"); a.SetTo("12345A");
} }
} }
[TestMethod] [TestMethod]
[ExpectedException(typeof(ArgumentException))] public void FloatToStringTruncated()
public void RationalFromInvalidString2()
{
using (var a = new HugeRational())
{
a.SetTo("12345/13345A");
}
}
[TestMethod]
public void RationalToStringTruncated()
{ {
using (var d = new HugeInt("115756986668303657898962467957")) using (var d = new HugeInt("115756986668303657898962467957"))
using (var e = new HugeInt(d ^ 10)) using (var e = new HugeInt(d ^ 10))
{ {
var s = e.ToString(10); var s = e.ToString(10);
var n = string.Concat("123456789".Select(c => new string(c, 30))); using (var a = HugeFloat.Allocate(1200))
using (var a = new HugeRational(n + "/" + s))
{ {
Assert.AreEqual(n + "/" + s, a.ToString(10)); a.SetTo(s);
Assert.AreEqual("..." + n.Substring(n.Length - 256) + "/..." + s.Substring(s.Length - 256), a.ToString()); Assert.AreEqual(256, a.ToString().Replace("0.", "").Replace("@291", "").Length);
a.Value = -a; Assert.AreEqual(291, a.ToString(10).Replace("0.", "").Replace("@291", "").Length);
Assert.AreEqual("-..." + n.Substring(n.Length - 256) + "/..." + s.Substring(s.Length - 256), a.ToString());
} }
} }
} }
[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);
}
} }
} }

View File

@ -123,7 +123,7 @@ namespace MPIR
#pragma region object overrides #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) if(base < 2 || base > 62)
throw gcnew ArgumentOutOfRangeException("base", "Invalid base"); throw gcnew ArgumentOutOfRangeException("base", "Invalid base");
@ -153,7 +153,16 @@ namespace MPIR
str++; str++;
} }
result->Append((wchar_t)'@'); 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); (*__gmp_free_func)(allocatedStr, allocated);

View File

@ -763,7 +763,7 @@ namespace MPIR
} }
void FromString(String^ value, int base); void FromString(String^ value, int base);
MPTYPE(bool initialize); MPTYPE(bool initialize);
String^ ToString(int base, bool lowercase, int maxDigits); String^ ToString(int base, bool lowercase, int maxDigits, bool exponentInDecimal);
internal: internal:
virtual void DeallocateStruct() virtual void DeallocateStruct()
@ -896,7 +896,7 @@ namespace MPIR
/// </para>Setting MpirSettings.ToStringDigits to 0 removes the upper limit. /// </para>Setting MpirSettings.ToStringDigits to 0 removes the upper limit.
/// </summary> /// </summary>
/// <returns>A string representation of the number in decimal, possibly cut off if the number has more digits than MpirSettings.ToStringDigits.</returns> /// <returns>A string representation of the number in decimal, possibly cut off if the number has more digits than MpirSettings.ToStringDigits.</returns>
virtual String^ ToString() override { return ToString(10, false, MpirSettings::ToStringDigits); } virtual String^ ToString() override { return ToString(10, false, MpirSettings::ToStringDigits, false); }
/// <summary> /// <summary>
/// Converts the number to a string in the specified base. /// Converts the number to a string in the specified base.
@ -904,7 +904,7 @@ namespace MPIR
/// </para></summary> /// </para></summary>
/// <param name="base">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.</param> /// <param name="base">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.</param>
/// <returns>A string representation of the number in the specified base.</returns> /// <returns>A string representation of the number in the specified base.</returns>
String^ ToString(int base) { return ToString(base, false, 0); } String^ ToString(int base) { return ToString(base, false, 0, false); }
/// <summary> /// <summary>
/// Converts the number to a string in the specified base. /// Converts the number to a string in the specified base.
@ -916,7 +916,20 @@ namespace MPIR
/// <param name="lowercase">Indicates if lowercase or uppercase letters should be used for the output. /// <param name="lowercase">Indicates if lowercase or uppercase letters should be used for the output.
/// <para>This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used.</para></param> /// <para>This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used.</para></param>
/// <returns>A string representation of the number in the specified base.</returns> /// <returns>A string representation of the number in the specified base.</returns>
String^ ToString(int base, bool lowercase) { return ToString(base, lowercase, 0); } String^ ToString(int base, bool lowercase) { return ToString(base, lowercase, 0, false); }
/// <summary>
/// Converts the number to a string in the specified base.
/// <para>This method always produces the complete output regardless of the MpirSettings.ToStringDigits setting.
/// </para></summary>
/// <param name="base">The base to use for the output.
/// <para>The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the <paramref name="lowercase"/> argument.
/// </para>For bases larger than 36, the <paramref name="lowercase"/> argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61.</param>
/// <param name="lowercase">Indicates if lowercase or uppercase letters should be used for the output.
/// <para>This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used.</para></param>
/// <param name="exponentInDecimal">True to always show the exponent in decimal, False to use the same base as the mantissa</param>
/// <returns>A string representation of the number in the specified base.</returns>
String^ ToString(int base, bool lowercase, bool exponentInDecimal) { return ToString(base, lowercase, 0, exponentInDecimal); }
///// <summary> ///// <summary>
///// Returns the absolute value of the number as a ulong. ///// Returns the absolute value of the number as a ulong.