Browse Source

Merge pull request #729 from KaptenJon/Add-Extensions-To-Round-Numerics-Above-Zero

Add extension methods that allow round above zero
pull/752/head
Christoph Ruegg 5 years ago
committed by GitHub
parent
commit
710671a5e4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 96
      src/Numerics.Tests/PrecisionTest.cs
  2. 146
      src/Numerics/Precision.cs

96
src/Numerics.Tests/PrecisionTest.cs

@ -28,6 +28,7 @@
// </copyright>
using System;
using System.Numerics;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests
@ -1156,5 +1157,100 @@ namespace MathNet.Numerics.UnitTests
Assert.AreEqual(-1, double.NegativeInfinity.CompareTo(1.0, Precision.DoubleDecimalPlaces));
Assert.AreEqual(1, 1.0.CompareTo(double.NegativeInfinity, Precision.DoubleDecimalPlaces));
}
[Test]
[TestCase(100.3123, 3, 0)]
[TestCase(1100.6123, 3, 1000)]
[TestCase(1500.8123, 3, 2000)]
[TestCase(110003245.3123, 3, 110003000)]
[TestCase(110003245.3123, 1, 110003250)]
[TestCase(110003245.3123, -2, 110003245.31)]
[TestCase(110003245.3123, 0, 110003245)]
public void RoundAboveDecimal(decimal number, int digit, decimal expectedResult)
{
Assert.AreEqual(expectedResult, number.RoundAboveZero(digit));
}
[Test]
[TestCase(100.3123, 3, 0)]
[TestCase(1100.6123, 3, 1000)]
[TestCase(1500.8123, 3, 2000)]
[TestCase(110003245.3123, 3, 110003000)]
[TestCase(110003245.3123, 1, 110003250)]
[TestCase(110003245.3123, -2, 110003245.31)]
[TestCase(110003245.3123, 0, 110003245)]
public void RoundAboveDouble(double number, int digit, double expectedResult)
{
Assert.AreEqual(expectedResult,number.RoundAboveZero(digit));
}
[Test]
[TestCase(100.3123f, 3, 0f)]
[TestCase(1100.6123f, 3, 1000f)]
[TestCase(1500.8123f, 3, 2000f)]
[TestCase(11245.3123f, 3, 11000f)]
[TestCase(13245.3123f, 1, 13250f)]
[TestCase(13245.3123f, -2, 13245.31f)]
[TestCase(13245.3123f, 0, 13245f)]
public void RoundAboveFloat(float number, int digit, float expectedResult)
{
Assert.AreEqual(expectedResult,number.RoundAboveZero(digit));
}
[Test]
[TestCase(100, 3, 0)]
[TestCase(1100, 3, 1000)]
[TestCase(1500, 3, 2000)]
[TestCase(110003245, 3, 110003000)]
[TestCase(110003245, 1, 110003250)]
[TestCase(110003245, -2, 110003245)]
public void RoundAboveInt(int number, int digit, int expectedResult)
{
Assert.AreEqual(expectedResult,number.RoundAboveZero(digit));
}
[Test]
public void RoundAboveUint()
{
Assert.AreEqual(110003250,((uint)110003245).RoundAboveZero(1));
}
[Test]
public void RoundAboveUlong()
{
Assert.AreEqual(3250, ((ulong)3245).RoundAboveZero(1));
}
[Test]
[TestCase(110003245, 1, 110003250)]
public void RoundAboveLong(long number, int digit, int expectedResult)
{
Assert.AreEqual(expectedResult, number.RoundAboveZero(digit));
}
[Test]
public void RoundAboveShort()
{
Assert.AreEqual(3250, ((short)3245).RoundAboveZero(1));
}
[Test]
public void RoundAboveUshort()
{
Assert.AreEqual(3250,((ushort)3245).RoundAboveZero(1));
}
[Test]
public void RoundAboveBigInteger()
{
Assert.AreEqual(BigInteger.Zero,new BigInteger(100).RoundAboveZero(3));
Assert.AreEqual(new BigInteger(1000),new BigInteger(1100).RoundAboveZero(3));
Assert.AreEqual(new BigInteger(2000),new BigInteger(1500).RoundAboveZero(3));
Assert.AreEqual(new BigInteger(110003000), new BigInteger(110003245).RoundAboveZero(3));
Assert.AreEqual(new BigInteger(110003250), new BigInteger(110003245).RoundAboveZero(1));
Assert.AreEqual(new BigInteger(110003245), new BigInteger(110003245).RoundAboveZero(-2));
Assert.AreEqual(new BigInteger(110003245), new BigInteger(110003245).RoundAboveZero(0));
}
}
}

146
src/Numerics/Precision.cs

@ -28,6 +28,7 @@
// </copyright>
using System;
using System.Numerics;
using System.Runtime;
using System.Runtime.InteropServices;
@ -744,6 +745,151 @@ namespace MathNet.Numerics
return eps;
}
/// <summary>
/// Round to the number closest to 10^powerDigits.
/// </summary>
/// <param name="number">Number to be rounded</param>
/// <param name="powerDigits">For closest 1000 enter 3, 10^powerDigits. If lower then zero you will get decimal digits.</param>
/// <example>To round 123456789 to hundreds RoundAboveZero(123456789, 2) = 123456800 </example>
/// <returns>Rounded number</returns>
public static decimal RoundAboveZero(this decimal number, int powerDigits = 3)
{
if (powerDigits <= 0)
return Math.Round(number, powerDigits*-1,MidpointRounding.AwayFromZero);
return Math.Round(number / (decimal) Math.Pow(10, powerDigits),MidpointRounding.AwayFromZero) * (decimal) Math.Pow(10, powerDigits);
}
/// <summary>
/// Round to the number closest to 10^powerDigits.
/// </summary>
/// <param name="number">Number to be rounded</param>
/// <param name="powerDigits">For closest 1000 enter 3, 10^powerDigits. If lower then zero you will get decimal digits.</param>
/// <example>To round 123456789 to hundreds RoundAboveZero(123456789, 2) = 123456800 </example>
/// <returns>Rounded number</returns>
public static double RoundAboveZero(this double number, int powerDigits = 3)
{
if (powerDigits <= 0)
return Math.Round(number, powerDigits*-1,MidpointRounding.AwayFromZero);
return Math.Round(number / Math.Pow(10, powerDigits),MidpointRounding.AwayFromZero) * Math.Pow(10, powerDigits);
}
/// <summary>
/// Round to the number closest to 10^powerDigits.
/// </summary>
/// <param name="number">Number to be rounded</param>
/// <param name="powerDigits">For closest 1000 enter 3, 10^powerDigits. If lower then zero you will get decimal digits.</param>
/// <example>To round 123456789 to hundreds RoundAboveZero(123456789, 2) = 123456800 </example>
/// <returns>Rounded number</returns>
public static int RoundAboveZero(this int number, int powerDigits = 3)
{
if (powerDigits <= 0)
return number;
return (int) RoundAboveZero((decimal) number, powerDigits);
}
/// <summary>
/// Round to the number closest to 10^powerDigits.
/// </summary>
/// <param name="number">Number to be rounded</param>
/// <param name="powerDigits">For closest 1000 enter 3, 10^powerDigits. If lower then zero you will get decimal digits.</param>
/// <example>To round 123456789 to hundreds RoundAboveZero(123456789, 2) = 123456800 </example>
/// <returns>Rounded number</returns>
public static uint RoundAboveZero(this uint number, int powerDigits = 3)
{
if (powerDigits <= 0)
return number;
return (uint) RoundAboveZero((decimal) number, powerDigits);
}
/// <summary>
/// Round to the number closest to 10^powerDigits.
/// </summary>
/// <param name="number">Number to be rounded</param>
/// <param name="powerDigits">For closest 1000 enter 3, 10^powerDigits. If lower then zero you will get decimal digits.</param>
/// <example>To round 123456789 to hundreds RoundAboveZero(123456789, 2) = 123456800 </example>
/// <returns>Rounded number</returns>
public static ulong RoundAboveZero(this ulong number, int powerDigits = 3)
{
if (powerDigits <= 0)
return number;
return (ulong) RoundAboveZero((decimal) number, powerDigits);
}
/// <summary>
/// Round to the number closest to 10^powerDigits.
/// </summary>
/// <param name="number">Number to be rounded</param>
/// <param name="powerDigits">For closest 1000 enter 3, 10^powerDigits. If lower then zero you will get decimal digits.</param>
/// <example>To round 123456789 to hundreds RoundAboveZero(123456789, 2) = 123456800 </example>
/// <returns>Rounded number</returns>
public static long RoundAboveZero(this long number, int powerDigits = 3)
{
if (powerDigits <= 0)
return number;
return (long) RoundAboveZero((decimal) number, powerDigits);
}
/// <summary>
/// Round to the number closest to 10^powerDigits.
/// </summary>
/// <param name="number">Number to be rounded</param>
/// <param name="powerDigits">For closest 1000 enter 3, 10^powerDigits. If lower then zero you will get decimal digits.</param>
/// <example>To round 123456789 to hundreds RoundAboveZero(123456789, 2) = 123456800 </example>
/// <returns>Rounded number</returns>
public static short RoundAboveZero(this short number, int powerDigits = 3)
{
if (powerDigits <= 0)
return number;
return (short) RoundAboveZero((decimal) number, powerDigits);
}
/// <summary>
/// Round to the number closest to 10^powerDigits.
/// </summary>
/// <param name="number">Number to be rounded</param>
/// <param name="powerDigits">For closest 1000 enter 3, 10^powerDigits. If lower then zero you will get decimal digits.</param>
/// <example>To round 123456789 to hundreds RoundAboveZero(123456789, 2) = 123456800 </example>
/// <returns>Rounded number</returns>
public static ushort RoundAboveZero(this ushort number, int powerDigits = 3)
{
if (powerDigits <= 0)
return number;
return (ushort) RoundAboveZero((decimal) number, powerDigits);
}
/// <summary>
/// Round to the number closest to 10^powerDigits.
/// </summary>
/// <param name="number">Number to be rounded</param>
/// <param name="powerDigits">For closest 1000 enter 3, 10^powerDigits. If lower then zero you will get decimal digits.</param>
/// <example>To round 123456789 to hundreds RoundAboveZero(123456789, 2) = 123456800 </example>
/// <returns>Rounded number</returns>
public static float RoundAboveZero(this float number, int powerDigits = 3)
{
return (float) RoundAboveZero((decimal) number, powerDigits);
}
/// <summary>
/// Round to the number closest to 10^powerDigits.
/// </summary>
/// <param name="number">Number to be rounded</param>
/// <param name="powerDigits">For closest 1000 enter 3, 10^powerDigits. If lower then zero you will get decimal digits.</param>
/// <example>To round 123456789 to hundreds RoundAboveZero(123456789, 2) = 123456800 </example>
/// <returns>Rounded number</returns>
public static BigInteger RoundAboveZero(this BigInteger number, int powerDigits = 3)
{
if (powerDigits <= 0)
return number;
var onelarger = number / BigInteger.Pow(10, powerDigits-1);
var divided = onelarger / 10;
var lastDigit = onelarger - divided * 10;
if (lastDigit >= 5)
divided += 1;
return divided * BigInteger.Pow(10, powerDigits);
}
/// <summary>
/// Calculates the actual positive double precision machine epsilon - the smallest number that can be added to 1, yielding a results different than 1.
/// This is also known as unit roundoff error. According to the definition of Prof. Higham.

Loading…
Cancel
Save