From ed83bb8609c21fc219ad08902d5a57a9ffc86aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Pa=C5=BEourek?= Date: Tue, 15 Jan 2019 19:35:23 +0100 Subject: [PATCH] Fixed bug in the magnitude computation. (thanks to 0jpq0, closes #20) --- src/Rationals/BigIntegerUtils.cs | 24 +++++++++++++++ src/Rationals/ExtendedProperties.cs | 29 +++++++++++++++++-- .../ExtendedPropertiesTests.cs | 2 ++ 3 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/Rationals/BigIntegerUtils.cs diff --git a/src/Rationals/BigIntegerUtils.cs b/src/Rationals/BigIntegerUtils.cs new file mode 100644 index 0000000..1f7ec6a --- /dev/null +++ b/src/Rationals/BigIntegerUtils.cs @@ -0,0 +1,24 @@ +using System.Numerics; + +namespace Rationals +{ + internal static class BigIntegerUtils + { + /// + /// Returns the number of digits of the given number + /// + public static int GetNumberOfDigits(BigInteger x) + { + x = BigInteger.Abs(x); + + var digits = 0; + while (x > 0) + { + digits++; + x /= 10; + } + + return digits; + } + } +} \ No newline at end of file diff --git a/src/Rationals/ExtendedProperties.cs b/src/Rationals/ExtendedProperties.cs index ce32430..c3cd4b1 100644 --- a/src/Rationals/ExtendedProperties.cs +++ b/src/Rationals/ExtendedProperties.cs @@ -46,9 +46,32 @@ public int Magnitude if (IsZero) return 0; - var numLog = BigInteger.Log10(BigInteger.Abs(Numerator)); - var denLog = BigInteger.Log10(BigInteger.Abs(Denominator)); - return (int)Math.Floor(numLog - denLog); + // thanks to 0jpq0 for this magnitude algorithm + // https://github.com/tompazourek/Rationals/issues/20#issue-398771661 + + var numeratorDigits = BigIntegerUtils.GetNumberOfDigits(Numerator); + var denominatorDigits = BigIntegerUtils.GetNumberOfDigits(Denominator); + + var magnitude = numeratorDigits - denominatorDigits; + + var numeratorAbs = BigInteger.Abs(Numerator); + var denominatorAbs = BigInteger.Abs(Denominator); + + if (numeratorDigits > denominatorDigits) + { + denominatorAbs *= BigInteger.Pow(10, numeratorDigits - denominatorDigits); + } + else if (numeratorDigits < denominatorDigits) + { + numeratorAbs *= BigInteger.Pow(10, denominatorDigits - numeratorDigits); + } + + if (numeratorAbs < denominatorAbs) + { + magnitude--; + } + + return magnitude; } } } diff --git a/tests/Rationals.Tests/ExtendedPropertiesTests.cs b/tests/Rationals.Tests/ExtendedPropertiesTests.cs index 99a6b65..fd21c70 100644 --- a/tests/Rationals.Tests/ExtendedPropertiesTests.cs +++ b/tests/Rationals.Tests/ExtendedPropertiesTests.cs @@ -10,6 +10,8 @@ public class ExtendedPropertiesTests [InlineData(2, 1, 0)] [InlineData(0, 1, 0)] [InlineData(10, 1, 1)] + [InlineData(100, 1, 2)] + [InlineData(1000, 1, 3)] [InlineData(11, 1, 1)] [InlineData(11, 2, 0)] [InlineData(1, 2, -1)]