I need to round a decimal to a specific number of significant figures. I have a library that can be simplified as shown.
decimal a = Math.Round(20.051M * 100M) / 100M; // 20.05
decimal b = Math.Round(20.001M * 100M) / 100M; // 20;
Clearly I lost the trailing zeros when performing the Round
, I can get them back by adding .00M
Is there a way to do this dynamically, if I were rounding to five significant figures I would want to use .000M
, likewise if my decimal was < 10 .000M
would be appropriate.
b = b + .00M; // 20.00
For reference here is the actual rounding method.
DecimalExtensions.cs
private static readonly decimal[] Pows = Enumerable.Range(-28, 57).Select(p => (decimal)Math.Pow(10, p)).ToArray();
/// <remarks>https://stackoverflow.com/a/18146056/3194005</remarks>
public static decimal RoundToSignificantFigures(this decimal value, int significantFigures)
{
if (value == 0)
return 0;
int d = Log10Ceiling(Math.Abs(value));
int power = significantFigures - d;
decimal magnitude = (decimal)Math.Pow(10, power);
return Math.Round(value * magnitude) / magnitude;
}
private static int Log10Ceiling(decimal value)
{
int log10 = Array.BinarySearch(Pows, value);
return (log10 >= 0 ? log10 : ~log10) - 28;
}