mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-22 14:48:47 +00:00
feat: add math extensions for BigInteger
This commit is contained in:
parent
5e4af9a9e1
commit
dc1b9d6c04
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
- X10D: Added extension methods for `DateOnly`, for parity with `DateTime` and `DateTimeOffset`.
|
- X10D: Added extension methods for `DateOnly`, for parity with `DateTime` and `DateTimeOffset`.
|
||||||
|
- X10D: Added math-related extension methods for `BigInteger`.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- X10D: `DateTime.Age(DateTime)` and `DateTimeOffset.Age(DateTimeOffset)` parameter renamed from `asOf` to `referenceDate`.
|
- X10D: `DateTime.Age(DateTime)` and `DateTimeOffset.Age(DateTimeOffset)` parameter renamed from `asOf` to `referenceDate`.
|
||||||
|
105
X10D.Tests/src/Math/BigIntegerTests.Wrap.cs
Normal file
105
X10D.Tests/src/Math/BigIntegerTests.Wrap.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using X10D.Math;
|
||||||
|
|
||||||
|
namespace X10D.Tests.Math;
|
||||||
|
|
||||||
|
public partial class BigIntegerTests
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class WrapTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void Wrap_ShouldReturnLow_WhenValueIsEqualToLow()
|
||||||
|
{
|
||||||
|
BigInteger value = 10;
|
||||||
|
BigInteger low = 10;
|
||||||
|
BigInteger high = 20;
|
||||||
|
|
||||||
|
BigInteger result = value.Wrap(low, high);
|
||||||
|
|
||||||
|
Assert.AreEqual(low, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Wrap_ShouldReturnHigh_WhenValueIsEqualToHigh()
|
||||||
|
{
|
||||||
|
BigInteger value = 20;
|
||||||
|
BigInteger low = 10;
|
||||||
|
BigInteger high = 20;
|
||||||
|
|
||||||
|
BigInteger result = value.Wrap(low, high);
|
||||||
|
|
||||||
|
Assert.AreEqual(low, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Wrap_ShouldReturnCorrectResult_WhenValueIsGreaterThanHigh()
|
||||||
|
{
|
||||||
|
BigInteger value = 30;
|
||||||
|
BigInteger low = 10;
|
||||||
|
BigInteger high = 20;
|
||||||
|
|
||||||
|
BigInteger result = value.Wrap(low, high);
|
||||||
|
|
||||||
|
Assert.AreEqual(low, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Wrap_ShouldReturnCorrectResult_WhenValueIsLessThanLow()
|
||||||
|
{
|
||||||
|
BigInteger value = 5;
|
||||||
|
BigInteger low = 10;
|
||||||
|
BigInteger high = 20;
|
||||||
|
|
||||||
|
BigInteger result = value.Wrap(low, high);
|
||||||
|
|
||||||
|
Assert.AreEqual(15L, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Wrap_ShouldReturnCorrectResult_WhenValueIsInBetweenLowAndHigh()
|
||||||
|
{
|
||||||
|
BigInteger value = 15;
|
||||||
|
BigInteger low = 10;
|
||||||
|
BigInteger high = 20;
|
||||||
|
|
||||||
|
BigInteger result = value.Wrap(low, high);
|
||||||
|
|
||||||
|
Assert.AreEqual(value, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Wrap_ShouldReturnZero_WhenValueIsEqualToLength()
|
||||||
|
{
|
||||||
|
BigInteger value = 10;
|
||||||
|
BigInteger length = 10;
|
||||||
|
|
||||||
|
BigInteger result = value.Wrap(length);
|
||||||
|
|
||||||
|
Assert.AreEqual(0L, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Wrap_ShouldReturnValue_WhenValueIsLessThanLength()
|
||||||
|
{
|
||||||
|
BigInteger value = 5;
|
||||||
|
BigInteger length = 10;
|
||||||
|
|
||||||
|
BigInteger result = value.Wrap(length);
|
||||||
|
|
||||||
|
Assert.AreEqual(value, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Wrap_ShouldReturnCorrectResult_WhenValueIsGreaterThanLength()
|
||||||
|
{
|
||||||
|
BigInteger value = 15;
|
||||||
|
BigInteger length = 10;
|
||||||
|
|
||||||
|
BigInteger result = value.Wrap(length);
|
||||||
|
|
||||||
|
Assert.AreEqual(5L, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
159
X10D.Tests/src/Math/BigIntegerTests.cs
Normal file
159
X10D.Tests/src/Math/BigIntegerTests.cs
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using X10D.Math;
|
||||||
|
|
||||||
|
namespace X10D.Tests.Math;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public partial class BigIntegerTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void DigitalRootShouldBeCorrect()
|
||||||
|
{
|
||||||
|
BigInteger value = 238;
|
||||||
|
Assert.AreEqual(4, value.DigitalRoot());
|
||||||
|
Assert.AreEqual(4, (-value).DigitalRoot());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void FactorialShouldBeCorrect()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(1, ((BigInteger)0).Factorial());
|
||||||
|
Assert.AreEqual(1, ((BigInteger)1).Factorial());
|
||||||
|
Assert.AreEqual(2, ((BigInteger)2).Factorial());
|
||||||
|
Assert.AreEqual(6, ((BigInteger)3).Factorial());
|
||||||
|
Assert.AreEqual(24, ((BigInteger)4).Factorial());
|
||||||
|
Assert.AreEqual(120, ((BigInteger)5).Factorial());
|
||||||
|
Assert.AreEqual(720, ((BigInteger)6).Factorial());
|
||||||
|
Assert.AreEqual(5040, ((BigInteger)7).Factorial());
|
||||||
|
Assert.AreEqual(40320, ((BigInteger)8).Factorial());
|
||||||
|
Assert.AreEqual(362880, ((BigInteger)9).Factorial());
|
||||||
|
Assert.AreEqual(3628800, ((BigInteger)10).Factorial());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GreatestCommonFactor_ShouldBe1_ForPrimeNumbers()
|
||||||
|
{
|
||||||
|
BigInteger first = 5L;
|
||||||
|
BigInteger second = 7L;
|
||||||
|
|
||||||
|
BigInteger multiple = first.GreatestCommonFactor(second);
|
||||||
|
|
||||||
|
Assert.AreEqual(1L, multiple);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GreatestCommonFactor_ShouldBe6_Given12And18()
|
||||||
|
{
|
||||||
|
BigInteger first = 12L;
|
||||||
|
BigInteger second = 18L;
|
||||||
|
|
||||||
|
BigInteger multiple = first.GreatestCommonFactor(second);
|
||||||
|
|
||||||
|
Assert.AreEqual(6L, multiple);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void IsOddShouldBeCorrect()
|
||||||
|
{
|
||||||
|
BigInteger one = 1;
|
||||||
|
BigInteger two = 2;
|
||||||
|
|
||||||
|
Assert.IsTrue(one.IsOdd());
|
||||||
|
Assert.IsFalse(two.IsOdd());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LowestCommonMultiple_ShouldReturnCorrectValue_WhenCalledWithValidInput()
|
||||||
|
{
|
||||||
|
BigInteger value1 = 2;
|
||||||
|
BigInteger value2 = 3;
|
||||||
|
BigInteger expected = 6;
|
||||||
|
|
||||||
|
BigInteger result = value1.LowestCommonMultiple(value2);
|
||||||
|
|
||||||
|
Assert.AreEqual(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LowestCommonMultiple_ShouldReturnZero_WhenCalledWithZero()
|
||||||
|
{
|
||||||
|
BigInteger value1 = 0;
|
||||||
|
BigInteger value2 = 10;
|
||||||
|
BigInteger expected = 0;
|
||||||
|
|
||||||
|
BigInteger result = value1.LowestCommonMultiple(value2);
|
||||||
|
|
||||||
|
Assert.AreEqual(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LowestCommonMultiple_ShouldReturnGreaterValue_WhenCalledWithOne()
|
||||||
|
{
|
||||||
|
BigInteger value1 = 1;
|
||||||
|
BigInteger value2 = 10;
|
||||||
|
BigInteger expected = 10;
|
||||||
|
|
||||||
|
BigInteger result1 = value1.LowestCommonMultiple(value2);
|
||||||
|
BigInteger result2 = value2.LowestCommonMultiple(value1);
|
||||||
|
|
||||||
|
Assert.AreEqual(expected, result1);
|
||||||
|
Assert.AreEqual(expected, result2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LowestCommonMultiple_ShouldReturnOtherValue_WhenCalledWithSameValue()
|
||||||
|
{
|
||||||
|
BigInteger value1 = 5;
|
||||||
|
BigInteger value2 = 5;
|
||||||
|
BigInteger expected = 5;
|
||||||
|
|
||||||
|
BigInteger result = value1.LowestCommonMultiple(value2);
|
||||||
|
|
||||||
|
Assert.AreEqual(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void LowestCommonMultiple_ShouldReturnCorrectValue_WhenCalledWithNegativeValues()
|
||||||
|
{
|
||||||
|
BigInteger value1 = -2;
|
||||||
|
BigInteger value2 = 3;
|
||||||
|
BigInteger expected = -6;
|
||||||
|
|
||||||
|
BigInteger result = value1.LowestCommonMultiple(value2);
|
||||||
|
|
||||||
|
Assert.AreEqual(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MultiplicativePersistence_ShouldReturn1_ForAnyDigitBeing0()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(1, ((BigInteger)10).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(1, ((BigInteger)201).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(1, ((BigInteger)200).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(1, ((BigInteger)20007).MultiplicativePersistence());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MultiplicativePersistence_ShouldBeCorrect_ForRecordHolders()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(0, ((BigInteger)0).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(1, ((BigInteger)10).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(2, ((BigInteger)25).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(3, ((BigInteger)39).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(4, ((BigInteger)77).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(5, ((BigInteger)679).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(6, ((BigInteger)6788).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(7, ((BigInteger)68889).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(8, ((BigInteger)2677889).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(9, ((BigInteger)26888999).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(10, ((BigInteger)3778888999).MultiplicativePersistence());
|
||||||
|
Assert.AreEqual(11, ((BigInteger)277777788888899).MultiplicativePersistence());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void NegativeFactorialShouldThrow()
|
||||||
|
{
|
||||||
|
Assert.ThrowsException<ArithmeticException>(() => ((BigInteger)(-1)).Factorial());
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System.Reflection;
|
using System.Numerics;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using X10D.Math;
|
using X10D.Math;
|
||||||
@ -26,6 +27,7 @@ public class IsPrimeTests
|
|||||||
|
|
||||||
Assert.IsTrue(value.IsPrime());
|
Assert.IsTrue(value.IsPrime());
|
||||||
Assert.IsTrue(((long)value).IsPrime());
|
Assert.IsTrue(((long)value).IsPrime());
|
||||||
|
Assert.IsTrue(((BigInteger)value).IsPrime());
|
||||||
|
|
||||||
if (value is >= byte.MinValue and <= byte.MaxValue)
|
if (value is >= byte.MinValue and <= byte.MaxValue)
|
||||||
{
|
{
|
||||||
@ -68,6 +70,7 @@ public class IsPrimeTests
|
|||||||
Assert.IsFalse(value.IsPrime());
|
Assert.IsFalse(value.IsPrime());
|
||||||
Assert.IsFalse(((int)value).IsPrime());
|
Assert.IsFalse(((int)value).IsPrime());
|
||||||
Assert.IsFalse(((long)value).IsPrime());
|
Assert.IsFalse(((long)value).IsPrime());
|
||||||
|
Assert.IsFalse(((BigInteger)value).IsPrime());
|
||||||
|
|
||||||
if (value is >= sbyte.MinValue and <= sbyte.MaxValue)
|
if (value is >= sbyte.MinValue and <= sbyte.MaxValue)
|
||||||
{
|
{
|
||||||
@ -85,6 +88,7 @@ public class IsPrimeTests
|
|||||||
Assert.IsFalse(((byte)value).IsPrime());
|
Assert.IsFalse(((byte)value).IsPrime());
|
||||||
Assert.IsFalse(((short)value).IsPrime());
|
Assert.IsFalse(((short)value).IsPrime());
|
||||||
Assert.IsFalse(((long)value).IsPrime());
|
Assert.IsFalse(((long)value).IsPrime());
|
||||||
|
Assert.IsFalse(((BigInteger)value).IsPrime());
|
||||||
|
|
||||||
Assert.IsFalse(((sbyte)value).IsPrime());
|
Assert.IsFalse(((sbyte)value).IsPrime());
|
||||||
Assert.IsFalse(((ushort)value).IsPrime());
|
Assert.IsFalse(((ushort)value).IsPrime());
|
||||||
@ -103,6 +107,7 @@ public class IsPrimeTests
|
|||||||
Assert.AreEqual(expected, ((short)value).IsPrime());
|
Assert.AreEqual(expected, ((short)value).IsPrime());
|
||||||
Assert.AreEqual(expected, value.IsPrime());
|
Assert.AreEqual(expected, value.IsPrime());
|
||||||
Assert.AreEqual(expected, ((long)value).IsPrime());
|
Assert.AreEqual(expected, ((long)value).IsPrime());
|
||||||
|
Assert.AreEqual(expected, ((BigInteger)value).IsPrime());
|
||||||
|
|
||||||
Assert.AreEqual(expected, ((ushort)value).IsPrime());
|
Assert.AreEqual(expected, ((ushort)value).IsPrime());
|
||||||
Assert.AreEqual(expected, ((uint)value).IsPrime());
|
Assert.AreEqual(expected, ((uint)value).IsPrime());
|
||||||
@ -121,6 +126,7 @@ public class IsPrimeTests
|
|||||||
Assert.AreEqual(expected, ((short)value).IsPrime());
|
Assert.AreEqual(expected, ((short)value).IsPrime());
|
||||||
Assert.AreEqual(expected, ((int)value).IsPrime());
|
Assert.AreEqual(expected, ((int)value).IsPrime());
|
||||||
Assert.AreEqual(expected, ((long)value).IsPrime());
|
Assert.AreEqual(expected, ((long)value).IsPrime());
|
||||||
|
Assert.AreEqual(expected, ((BigInteger)value).IsPrime());
|
||||||
|
|
||||||
Assert.AreEqual(expected, ((ushort)value).IsPrime());
|
Assert.AreEqual(expected, ((ushort)value).IsPrime());
|
||||||
Assert.AreEqual(expected, ((uint)value).IsPrime());
|
Assert.AreEqual(expected, ((uint)value).IsPrime());
|
||||||
|
253
X10D/src/Math/BigIntegerExtensions.cs
Normal file
253
X10D/src/Math/BigIntegerExtensions.cs
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
using System.Diagnostics.Contracts;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using X10D.CompilerServices;
|
||||||
|
|
||||||
|
namespace X10D.Math;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Math-related extension methods for <see cref="BigInteger" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class BigIntegerExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Computes the digital root of this 8-bit integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose digital root to compute.</param>
|
||||||
|
/// <returns>The digital root of <paramref name="value" />.</returns>
|
||||||
|
/// <remarks>The digital root is defined as the recursive sum of digits until that result is a single digit.</remarks>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The digital root is defined as the recursive sum of digits until that result is a single digit.</para>
|
||||||
|
/// <para>For example, the digital root of 239 is 5: <c>2 + 3 + 9 = 14</c>, then <c>1 + 4 = 5</c>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
[Pure]
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
public static int DigitalRoot(this BigInteger value)
|
||||||
|
{
|
||||||
|
BigInteger root = BigInteger.Abs(value).Mod(9);
|
||||||
|
return (int)(root == 0 ? 9 : root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the factorial of the current 64-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose factorial to compute.</param>
|
||||||
|
/// <returns>The factorial of <paramref name="value" />.</returns>
|
||||||
|
/// <exception cref="ArithmeticException"><paramref name="value" /> is less than 0.</exception>
|
||||||
|
[Pure]
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
public static BigInteger Factorial(this BigInteger value)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
throw new ArithmeticException(nameof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInteger result = 1;
|
||||||
|
for (var i = 1L; i <= value; i++)
|
||||||
|
{
|
||||||
|
result *= i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the greatest common factor between this, and another, <see cref="BigInteger" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The first value.</param>
|
||||||
|
/// <param name="other">The second value.</param>
|
||||||
|
/// <returns>The greatest common factor between <paramref name="value" /> and <paramref name="other" />.</returns>
|
||||||
|
[Pure]
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
public static BigInteger GreatestCommonFactor(this BigInteger value, BigInteger other)
|
||||||
|
{
|
||||||
|
while (other != 0)
|
||||||
|
{
|
||||||
|
(value, other) = (other, value % other);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the current value is not evenly divisible by 2.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose parity to check.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if <paramref name="value" /> is not evenly divisible by 2, or <see langword="false" />
|
||||||
|
/// otherwise.
|
||||||
|
/// </returns>
|
||||||
|
[Pure]
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
public static bool IsOdd(this BigInteger value)
|
||||||
|
{
|
||||||
|
return !value.IsEven;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the current value is a prime number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose primality to check.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if <paramref name="value" /> is prime; otherwise, <see langword="false" />.
|
||||||
|
/// </returns>
|
||||||
|
[Pure]
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
public static bool IsPrime(this BigInteger value)
|
||||||
|
{
|
||||||
|
if (value <= 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value <= 3)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.IsEven || value % 3 == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var iterator = 5L; iterator * iterator <= value; iterator += 6)
|
||||||
|
{
|
||||||
|
if (value % iterator == 0 || value % (iterator + 2) == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the lowest common multiple between the current 64-bit signed integer, and another 64-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The first value.</param>
|
||||||
|
/// <param name="other">The second value.</param>
|
||||||
|
/// <returns>The lowest common multiple between <paramref name="value" /> and <paramref name="other" />.</returns>
|
||||||
|
[Pure]
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
public static BigInteger LowestCommonMultiple(this BigInteger value, BigInteger other)
|
||||||
|
{
|
||||||
|
if (value == 0 || other == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == 1)
|
||||||
|
{
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (other == 1)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value * other / value.GreatestCommonFactor(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a modulo operation which supports a negative dividend.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dividend">The dividend.</param>
|
||||||
|
/// <param name="divisor">The divisor.</param>
|
||||||
|
/// <returns>The result of <c>dividend mod divisor</c>.</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// The <c>%</c> operator (commonly called the modulo operator) in C# is not defined to be modulo, but is instead
|
||||||
|
/// remainder. This quirk inherently makes it difficult to use modulo in a negative context, as <c>x % y</c> where x is
|
||||||
|
/// negative will return a negative value, akin to <c>-(x % y)</c>, even if precedence is forced. This method provides a
|
||||||
|
/// modulo operation which supports negative dividends.
|
||||||
|
/// </remarks>
|
||||||
|
/// <author>ShreevatsaR, https://stackoverflow.com/a/1082938/1467293</author>
|
||||||
|
/// <license>CC-BY-SA 2.5</license>
|
||||||
|
[Pure]
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
public static BigInteger Mod(this BigInteger dividend, BigInteger divisor)
|
||||||
|
{
|
||||||
|
BigInteger r = dividend % divisor;
|
||||||
|
return r < 0 ? r + divisor : r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the multiplicative persistence of a specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose multiplicative persistence to calculate.</param>
|
||||||
|
/// <returns>The multiplicative persistence.</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// Multiplicative persistence is defined as the recursive digital product until that product is a single digit.
|
||||||
|
/// </remarks>
|
||||||
|
[Pure]
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
public static int MultiplicativePersistence(this BigInteger value)
|
||||||
|
{
|
||||||
|
var persistence = 0;
|
||||||
|
BigInteger product = BigInteger.Abs(value);
|
||||||
|
|
||||||
|
while (product > 9)
|
||||||
|
{
|
||||||
|
if (value % 10 == 0)
|
||||||
|
{
|
||||||
|
return persistence + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (value > 9)
|
||||||
|
{
|
||||||
|
value /= 10;
|
||||||
|
if (value % 10 == 0)
|
||||||
|
{
|
||||||
|
return persistence + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInteger newProduct = 1;
|
||||||
|
BigInteger currentProduct = product;
|
||||||
|
while (currentProduct > 0)
|
||||||
|
{
|
||||||
|
newProduct *= currentProduct % 10;
|
||||||
|
currentProduct /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
product = newProduct;
|
||||||
|
persistence++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return persistence;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wraps the current integer between a low and a high value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to wrap.</param>
|
||||||
|
/// <param name="low">The inclusive lower bound.</param>
|
||||||
|
/// <param name="high">The exclusive upper bound.</param>
|
||||||
|
/// <returns>The wrapped value.</returns>
|
||||||
|
[Pure]
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
public static BigInteger Wrap(this BigInteger value, BigInteger low, BigInteger high)
|
||||||
|
{
|
||||||
|
BigInteger difference = high - low;
|
||||||
|
return low + (((value - low) % difference) + difference) % difference;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wraps the current integer between 0 and a high value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to wrap.</param>
|
||||||
|
/// <param name="length">The exclusive upper bound.</param>
|
||||||
|
/// <returns>The wrapped value.</returns>
|
||||||
|
[Pure]
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
public static BigInteger Wrap(this BigInteger value, BigInteger length)
|
||||||
|
{
|
||||||
|
return ((value % length) + length) % length;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user