diff --git a/src/Rationals/BigIntegerRootUtils.Root.cs b/src/Rationals/BigIntegerRootUtils.cs similarity index 100% rename from src/Rationals/BigIntegerRootUtils.Root.cs rename to src/Rationals/BigIntegerRootUtils.cs diff --git a/src/Rationals/Comparisons.cs b/src/Rationals/Comparisons.cs index 73e6696..443e353 100644 --- a/src/Rationals/Comparisons.cs +++ b/src/Rationals/Comparisons.cs @@ -18,57 +18,57 @@ public partial struct Rational : { public int CompareTo(object obj) { - if (obj is sbyte) + if (obj is sbyte @sbyte) { - return CompareTo((sbyte)obj); + return CompareTo(@sbyte); } - if (obj is byte) + if (obj is byte b) { - return CompareTo((byte)obj); + return CompareTo(b); } - if (obj is short) + if (obj is short s) { - return CompareTo((short)obj); + return CompareTo(s); } - if (obj is ushort) + if (obj is ushort @ushort) { - return CompareTo((ushort)obj); + return CompareTo(@ushort); } - if (obj is int) + if (obj is int i) { - return CompareTo((int)obj); + return CompareTo(i); } - if (obj is uint) + if (obj is uint u) { - return CompareTo((uint)obj); + return CompareTo(u); } - if (obj is long) + if (obj is long l) { - return CompareTo((long)obj); + return CompareTo(l); } - if (obj is ulong) + if (obj is ulong @ulong) { - return CompareTo((ulong)obj); + return CompareTo(@ulong); } - if (obj is Rational) + if (obj is Rational rational) { - return CompareTo((Rational)obj); + return CompareTo(rational); } - if (obj is BigInteger) + if (obj is BigInteger integer) { - return CompareTo((BigInteger)obj); + return CompareTo(integer); } - return ReferenceEquals(obj, this) ? 0 : -1; + return -1; } public int CompareTo(BigInteger other) @@ -194,8 +194,8 @@ public bool Equals(ushort other) public override bool Equals(object other) { - if (other is Rational) - return Equals((Rational)other); + if (other is Rational rational) + return Equals(rational); if (other is short || other is ushort || diff --git a/src/Rationals/ExplicitFloatingPointConversions.cs b/src/Rationals/ExplicitFloatingPointConversions.cs index a092e97..7ae75fe 100644 --- a/src/Rationals/ExplicitFloatingPointConversions.cs +++ b/src/Rationals/ExplicitFloatingPointConversions.cs @@ -16,8 +16,7 @@ public static explicit operator decimal(Rational rational) var previousScale = 0M; while (numerator > 0) { - BigInteger rem; - var divided = BigInteger.DivRem(numerator, denominator, out rem); + var divided = BigInteger.DivRem(numerator, denominator, out var rem); if (scale == 0) { diff --git a/src/Rationals/ExtendedProperties.cs b/src/Rationals/ExtendedProperties.cs index 7bd8dab..edcdc5f 100644 --- a/src/Rationals/ExtendedProperties.cs +++ b/src/Rationals/ExtendedProperties.cs @@ -6,17 +6,17 @@ namespace Rationals public partial struct Rational { /// - /// True if the number is equal to zero + /// True if the number is equal to zero. /// public bool IsZero => Numerator.IsZero; /// - /// True if the number is equal to one + /// True if the number is equal to one. /// public bool IsOne => Numerator == Denominator; /// - /// Gets a number that indicates the sign (negative, positive, or zero) of the rational number + /// Gets a number that indicates the sign (negative, positive, or zero) of the rational number. /// public int Sign => Numerator.Sign * Denominator.Sign; diff --git a/src/Rationals/Formatting.cs b/src/Rationals/Formatting.cs index 982ce0d..99d07b5 100644 --- a/src/Rationals/Formatting.cs +++ b/src/Rationals/Formatting.cs @@ -24,8 +24,7 @@ public IEnumerable Digits var returnedAny = false; while (numerator > 0) { - BigInteger rem; - var divided = BigInteger.DivRem(numerator, denominator, out rem); + var divided = BigInteger.DivRem(numerator, denominator, out var rem); var digits = divided.ToString(CultureInfo.InvariantCulture); diff --git a/src/Rationals/Operations.cs b/src/Rationals/Operations.cs index 7f573bf..1014d12 100644 --- a/src/Rationals/Operations.cs +++ b/src/Rationals/Operations.cs @@ -6,10 +6,8 @@ namespace Rationals public partial struct Rational { /// - /// Multiplicative inverse of the rational number + /// Multiplicative inverse of the rational number. /// - /// - /// public static Rational Invert(Rational p) { var numerator = p.Denominator; @@ -19,10 +17,8 @@ public static Rational Invert(Rational p) } /// - /// Additive inverse of the rational number + /// Additive inverse of the rational number. /// - /// - /// public static Rational Negate(Rational p) { if (p.IsZero) @@ -47,9 +43,6 @@ public static Rational Negate(Rational p) /// /// Returns the sum of the two numbers. /// - /// - /// - /// public static Rational Add(Rational left, Rational right) { if (right.IsZero) @@ -67,9 +60,6 @@ public static Rational Add(Rational left, Rational right) /// /// Subtracts one number from another and returns result. /// - /// - /// - /// public static Rational Subtract(Rational left, Rational right) { if (right.IsZero) @@ -87,9 +77,6 @@ public static Rational Subtract(Rational left, Rational right) /// /// Returns product of the two numbers. /// - /// - /// - /// public static Rational Multiply(Rational left, Rational right) { if (left.IsZero || right.IsZero) @@ -104,9 +91,6 @@ public static Rational Multiply(Rational left, Rational right) /// /// Divides one number by another and returns result. /// - /// - /// - /// public static Rational Divide(Rational left, Rational right) { if (right.IsZero) @@ -122,11 +106,8 @@ public static Rational Divide(Rational left, Rational right) } /// - /// Exponentiation of the rational number to the given integer exponent + /// Exponentiation of the rational number to the given integer exponent. /// - /// - /// - /// public static Rational Pow(Rational number, int exponent) { if (exponent == 1) @@ -163,10 +144,8 @@ public static Rational Pow(Rational number, int exponent) } /// - /// Gets the absolute value of the rational number + /// Gets the absolute value of the rational number. /// - /// - /// public static Rational Abs(Rational p) { if (p.IsZero) @@ -179,10 +158,8 @@ public static Rational Abs(Rational p) } /// - /// Returns the base 10 logarithm of a rational number + /// Returns the base 10 logarithm of a rational number. /// - /// - /// public static double Log10(Rational p) { if (p.IsZero) @@ -193,10 +170,8 @@ public static double Log10(Rational p) } /// - /// Returns the natural (base e) logarithm of a rational number + /// Returns the natural (base e) logarithm of a rational number. /// - /// - /// public static double Log(Rational p) { if (p.IsZero) @@ -207,11 +182,8 @@ public static double Log(Rational p) } /// - /// Returns the logarithm of a rational number + /// Returns the logarithm of a rational number. /// - /// - /// - /// public static double Log(Rational p, double baseValue) { if (p.IsZero) @@ -222,12 +194,42 @@ public static double Log(Rational p, double baseValue) } /// - /// Root of the rational number to the given integer radix + /// Root of the rational number as double. /// - /// - /// - /// - public static Rational Root(Rational number, int radix) + public static double Root(Rational number, double radix) + { + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (radix == 1) + return (double)number; + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (radix == 0) + throw new InvalidOperationException("Cannot use zero radix."); + + if (number.IsOne) + return 1; + + if (number.IsZero) + { + if (radix < 0) + throw new DivideByZeroException("Cannot root zero to negative exponent."); + + return 0; + } + + if (number < 0) + { + throw new InvalidOperationException("Cannot compute root of negative number."); + } + + var result = Math.Pow((double)number, 1 / radix); + return result; + } + + /// + /// Root of the rational number to the given integer radix (experimental). + /// + public static Rational RationalRoot(Rational number, int radix) { if (radix == 1) return number; @@ -246,6 +248,11 @@ public static Rational Root(Rational number, int radix) return number; } + if (number < 0) + { + throw new InvalidOperationException("Cannot compute root of negative number."); + } + if (radix > 0) { var numerator = BigIntegerRootUtils.BigIntegerRoot(number.Numerator, radix); diff --git a/src/Rationals/Parsing.cs b/src/Rationals/Parsing.cs index bdf47c9..2ad1ab5 100644 --- a/src/Rationals/Parsing.cs +++ b/src/Rationals/Parsing.cs @@ -36,9 +36,7 @@ public static Rational Parse(string value, NumberStyles style, IFormatProvider p private static Rational Parse(string value, NumberStyles style, NumberFormatInfo info) { - Rational result; - - if (!TryParse(value, style, info, out result)) + if (!TryParse(value, style, info, out var result)) { throw new FormatException("Cannot parse string as Rational, the input is in incorrect format."); } @@ -86,8 +84,7 @@ private static bool TryParse(string value, NumberStyles style, NumberFormatInfo return false; } - BigInteger justWhole; - if (BigInteger.TryParse(value, style, info, out justWhole)) + if (BigInteger.TryParse(value, style, info, out var justWhole)) { result = new Rational(justWhole); return true; @@ -98,28 +95,27 @@ private static bool TryParse(string value, NumberStyles style, NumberFormatInfo public static Rational ParseDecimal(string value, decimal tolerance = 0) { - return ParseDecimal(value, NumberStyles.Float, NumberFormatInfo.CurrentInfo, tolerance); + return ParseDecimal(value, NumberStyles.Float, NumberFormatInfo.CurrentInfo); } public static Rational ParseDecimal(string value, NumberStyles style, decimal tolerance = 0) { - return ParseDecimal(value, style, NumberFormatInfo.CurrentInfo, tolerance); + return ParseDecimal(value, style, NumberFormatInfo.CurrentInfo); } public static Rational ParseDecimal(string value, IFormatProvider provider, decimal tolerance = 0) { - return ParseDecimal(value, NumberStyles.Float, NumberFormatInfo.GetInstance(provider), tolerance); + return ParseDecimal(value, NumberStyles.Float, NumberFormatInfo.GetInstance(provider)); } public static Rational ParseDecimal(string value, NumberStyles style, IFormatProvider provider, decimal tolerance = 0) { - return ParseDecimal(value, style, NumberFormatInfo.GetInstance(provider), tolerance); + return ParseDecimal(value, style, NumberFormatInfo.GetInstance(provider)); } - private static Rational ParseDecimal(string value, NumberStyles style, NumberFormatInfo info, decimal tolerance = 0) + private static Rational ParseDecimal(string value, NumberStyles style, NumberFormatInfo info) { - Rational result; - if (!TryParseDecimal(value, style, info, out result)) + if (!TryParseDecimal(value, style, info, out var result)) { throw new FormatException("Cannot parse string as Rational, the input is in incorrect format."); } @@ -139,9 +135,7 @@ public static bool TryParseDecimal(string value, NumberStyles style, IFormatProv private static bool TryParseDecimal(string value, NumberStyles style, NumberFormatInfo info, out Rational result, decimal tolerance = 0) { - decimal d; - - if (!decimal.TryParse(value, style, info, out d)) + if (!decimal.TryParse(value, style, info, out var d)) { result = default(Rational); return false; diff --git a/src/Rationals/WholeAndFraction.cs b/src/Rationals/WholeAndFraction.cs index 77af9c8..c472606 100644 --- a/src/Rationals/WholeAndFraction.cs +++ b/src/Rationals/WholeAndFraction.cs @@ -35,8 +35,7 @@ public BigInteger WholePart return wholePart; } - BigInteger remainder; - wholePart = BigInteger.DivRem(num, den, out remainder); + wholePart = BigInteger.DivRem(num, den, out var remainder); if (remainder != 0) wholePart--; diff --git a/tests/Rationals.Tests/ExplicitFloatingPointConversionsTests.cs b/tests/Rationals.Tests/ExplicitFloatingPointConversionsTests.cs index 590b372..12fa25d 100644 --- a/tests/Rationals.Tests/ExplicitFloatingPointConversionsTests.cs +++ b/tests/Rationals.Tests/ExplicitFloatingPointConversionsTests.cs @@ -7,8 +7,8 @@ namespace Rationals.Tests { public class ExplicitFloatingPointConversionsTests { - private const int doublePrecision = 14; - private const int floatPrecision = 6; + private const int DoublePrecision = 14; + private const int FloatPrecision = 6; [Theory] [InlineData(0.5, 1, 2)] @@ -230,7 +230,7 @@ public void ToDouble1() var converted = (double)rational; // assert - Assert.Equal(d, converted, doublePrecision); + Assert.Equal(d, converted, DoublePrecision); } [Fact] @@ -244,7 +244,7 @@ public void ToDouble2() var converted = (double)rational; // assert - Assert.Equal(d, converted, doublePrecision); + Assert.Equal(d, converted, DoublePrecision); } [Fact] @@ -259,7 +259,7 @@ public void ToDouble3() var converted = (double)rational; // assert - Assert.Equal(d, converted, doublePrecision); + Assert.Equal(d, converted, DoublePrecision); } [Fact] @@ -273,7 +273,7 @@ public void ToDouble4() var converted = (double)rational; // assert - Assert.Equal(d, converted, doublePrecision); + Assert.Equal(d, converted, DoublePrecision); } [Fact] @@ -287,7 +287,7 @@ public void ToDouble5() var converted = (double)rational; // assert - Assert.Equal(d, converted, doublePrecision); + Assert.Equal(d, converted, DoublePrecision); } [Fact] @@ -301,7 +301,7 @@ public void ToFloat1() var converted = (float)rational; // assert - Assert.Equal(d, converted, floatPrecision); + Assert.Equal(d, converted, FloatPrecision); } [Fact] @@ -315,7 +315,7 @@ public void ToFloat2() var converted = (float)rational; // assert - Assert.Equal(d, converted, floatPrecision); + Assert.Equal(d, converted, FloatPrecision); } [Fact] @@ -330,7 +330,7 @@ public void ToFloat3() var converted = (float)rational; // assert - Assert.Equal(d, converted, floatPrecision); + Assert.Equal(d, converted, FloatPrecision); } [Fact] @@ -344,7 +344,7 @@ public void ToFloat4() var converted = (float)rational; // assert - Assert.Equal(d, converted, floatPrecision); + Assert.Equal(d, converted, FloatPrecision); } [Fact] @@ -358,7 +358,7 @@ public void ToFloat5() var converted = (float)rational; // assert - Assert.Equal(d, converted, floatPrecision); + Assert.Equal(d, converted, FloatPrecision); } } } \ No newline at end of file diff --git a/tests/Rationals.Tests/OperationsTests.cs b/tests/Rationals.Tests/OperationsTests.cs index dd7a26c..bb600a6 100644 --- a/tests/Rationals.Tests/OperationsTests.cs +++ b/tests/Rationals.Tests/OperationsTests.cs @@ -387,7 +387,6 @@ public void Subtraction3() Assert.Equal(-(Rational)4 / 3, result); } - [Fact] public void Subtraction4() { @@ -675,6 +674,70 @@ public void Logarithm5() Assert.True(double.IsNaN(result)); } + [Fact] + public void RationalRoot1() + { + // arrange + var value = (Rational)25 / 16; + const int radix = 2; + + // action + var result = Rational.RationalRoot(value, radix); + + // assert + Assert.Equal((Rational)5 / 4, result); + } + + [Fact] + public void RationalRoot2() + { + // arrange + var value = (Rational)16 / 25; + const int radix = -2; + + // action + var result = Rational.RationalRoot(value, radix); + + // assert + Assert.Equal((Rational)5 / 4, result); + } + + [Fact] + public void RationalRoot3() + { + // arrange + var value = (Rational)5 / -4; + const int radix = 1; + + // action + var result = Rational.RationalRoot(value, radix); + + // assert + Assert.Equal((Rational)5 / -4, result); + } + + [Fact] + public void RationalRoot4() + { + // arrange + var value = Rational.Zero; + const int radix = 0; + + // action + Assert.Throws(() => Rational.RationalRoot(value, radix)); + } + + [Fact] + public void RationalRoot5() + { + // arrange + var value = -(Rational)100 / 4; + const int radix = 2; + + // action + Assert.Throws(() => Rational.RationalRoot(value, radix)); + } + [Fact] public void Root1() { @@ -686,7 +749,7 @@ public void Root1() var result = Rational.Root(value, radix); // assert - Assert.Equal((Rational)5 / 4, result); + Assert.Equal((double)5 / 4, result); } [Fact] @@ -700,7 +763,7 @@ public void Root2() var result = Rational.Root(value, radix); // assert - Assert.Equal((Rational)5 / 4, result); + Assert.Equal((double)5 / 4, result); } [Fact] @@ -714,7 +777,7 @@ public void Root3() var result = Rational.Root(value, radix); // assert - Assert.Equal((Rational)5 / -4, result); + Assert.Equal((double)5 / -4, result); } [Fact] @@ -736,10 +799,7 @@ public void Root5() const int radix = 2; // action - var result = Rational.Root(value, radix); - - // assert - Assert.Equal((Rational)10 / 2, result); + Assert.Throws(() => Rational.Root(value, radix)); } } } \ No newline at end of file