Skip to content

Commit

Permalink
Merge pull request #610 from klaus78/Issue609
Browse files Browse the repository at this point in the history
adding parameter decimals toMetric(). Fixes #609
  • Loading branch information
Oren Novotny committed Apr 18, 2017
2 parents d3bb686 + ce9efae commit 283b233
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 44 deletions.
25 changes: 16 additions & 9 deletions src/Humanizer.Tests.Shared/MetricNumeralTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,25 @@ public void TestAllSymbolsAsInt(int exponent)
}

[Theory]
[InlineData("0", 0d, false, true)]
[InlineData("123", 123d, false, true)]
[InlineData("-123", (-123d), false, true)]
[InlineData("1.23k", 1230d, false, true)]
[InlineData("1 k", 1000d, true, true)]
[InlineData("1 kilo", 1000d, true, false)]
[InlineData("1milli", 1E-3, false, false)]
public void ToMetric(string expected, double input, bool hasSpace, bool useSymbol)
[InlineData("0", 0d, false, true, null)]
[InlineData("123", 123d, false, true, null)]
[InlineData("-123", (-123d), false, true, null)]
[InlineData("1.23k", 1230d, false, true, null)]
[InlineData("1 k", 1000d, true, true, null)]
[InlineData("1 kilo", 1000d, true, false, null)]
[InlineData("1milli", 1E-3, false, false, null)]
[InlineData("1milli", 1E-3, false, false, null)]
[InlineData("1.23milli", 1.234E-3, false, false, 2)]
[InlineData("12.34k", 12345, false, true, 2)]
[InlineData("12k", 12345, false, true, 0)]
[InlineData("-3.9m", -3.91e-3, false, true, 1)]
public void ToMetric(string expected, double input, bool hasSpace, bool useSymbol, int? decimals)
{
Assert.Equal(expected, input.ToMetric(hasSpace, useSymbol));
Assert.Equal(expected, input.ToMetric(hasSpace, useSymbol, decimals));
}



[Theory]
[InlineData(1E+27)]
[InlineData(1E-27)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,8 @@ namespace Humanizer
public class static MetricNumeralExtensions
{
public static double FromMetric(this string input) { }
public static string ToMetric(this int input, bool hasSpace = False, bool useSymbol = True) { }
public static string ToMetric(this double input, bool hasSpace = False, bool useSymbol = True) { }
public static string ToMetric(this int input, bool hasSpace = False, bool useSymbol = True, System.Nullable<int> decimals = null) { }
public static string ToMetric(this double input, bool hasSpace = False, bool useSymbol = True, System.Nullable<int> decimals = null) { }
}
public class NoMatchFoundException : System.Exception
{
Expand Down
72 changes: 39 additions & 33 deletions src/Humanizer/MetricNumeralExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,27 +90,28 @@ public static double FromMetric(this string input)
return BuildNumber(input, input[input.Length - 1]);
}

/// <summary>
/// Converts a number into a valid and Human-readable Metric representation.
/// </summary>
/// <remarks>
/// Inspired by a snippet from Thom Smith.
/// See <a href="http://stackoverflow.com/questions/12181024/formatting-a-number-with-a-metric-prefix">this link</a> for more.
/// </remarks>
/// <param name="input">Number to convert to a Metric representation.</param>
/// <param name="hasSpace">True will split the number and the symbol with a whitespace.</param>
/// <param name="useSymbol">True will use symbol instead of name</param>
/// <example>
/// <code>
/// 1000.ToMetric() => "1k"
/// 123.ToMetric() => "123"
/// 1E-1.ToMetric() => "100m"
/// </code>
/// </example>
/// <returns>A valid Metric representation</returns>
public static string ToMetric(this int input, bool hasSpace = false, bool useSymbol = true)
/// <summary>
/// Converts a number into a valid and Human-readable Metric representation.
/// </summary>
/// <remarks>
/// Inspired by a snippet from Thom Smith.
/// See <a href="http://stackoverflow.com/questions/12181024/formatting-a-number-with-a-metric-prefix">this link</a> for more.
/// </remarks>
/// <param name="input">Number to convert to a Metric representation.</param>
/// <param name="hasSpace">True will split the number and the symbol with a whitespace.</param>
/// <param name="useSymbol">True will use symbol instead of name</param>
/// <param name="decimals">If not null it is the numbers of decimals to round the number to</param>
/// <example>
/// <code>
/// 1000.ToMetric() => "1k"
/// 123.ToMetric() => "123"
/// 1E-1.ToMetric() => "100m"
/// </code>
/// </example>
/// <returns>A valid Metric representation</returns>
public static string ToMetric(this int input, bool hasSpace = false, bool useSymbol = true, int? decimals = null)
{
return ((double)input).ToMetric(hasSpace, useSymbol);
return ((double)input).ToMetric(hasSpace, useSymbol, decimals);
}

/// <summary>
Expand All @@ -123,6 +124,7 @@ public static string ToMetric(this int input, bool hasSpace = false, bool useSym
/// <param name="input">Number to convert to a Metric representation.</param>
/// <param name="hasSpace">True will split the number and the symbol with a whitespace.</param>
/// <param name="useSymbol">True will use symbol instead of name</param>
/// <param name="decimals">If not null it is the numbers of decimals to round the number to</param>
/// <example>
/// <code>
/// 1000d.ToMetric() => "1k"
Expand All @@ -131,14 +133,14 @@ public static string ToMetric(this int input, bool hasSpace = false, bool useSym
/// </code>
/// </example>
/// <returns>A valid Metric representation</returns>
public static string ToMetric(this double input, bool hasSpace = false, bool useSymbol = true)
public static string ToMetric(this double input, bool hasSpace = false, bool useSymbol = true, int? decimals = null)
{
if (input.Equals(0))
return input.ToString();
if (input.IsOutOfRange())
throw new ArgumentOutOfRangeException(nameof(input));

return BuildRepresentation(input, hasSpace, useSymbol);
return BuildRepresentation(input, hasSpace, useSymbol, decimals);
}

/// <summary>
Expand Down Expand Up @@ -199,19 +201,20 @@ private static string ReplaceNameBySymbol(string input)
current.Replace(name.Value, name.Key.ToString()));
}

/// <summary>
/// Build a Metric representation of the number.
/// </summary>
/// <param name="input">Number to convert to a Metric representation.</param>
/// <param name="hasSpace">True will split the number and the symbol with a whitespace.</param>
/// <param name="useSymbol">True will use symbol instead of name</param>
/// <returns>A number in a Metric representation</returns>
private static string BuildRepresentation(double input, bool hasSpace, bool useSymbol)
/// <summary>
/// Build a Metric representation of the number.
/// </summary>
/// <param name="input">Number to convert to a Metric representation.</param>
/// <param name="hasSpace">True will split the number and the symbol with a whitespace.</param>
/// <param name="useSymbol">True will use symbol instead of name</param>
/// <param name="decimals">If not null it is the numbers of decimals to round the number to</param>
/// <returns>A number in a Metric representation</returns>
private static string BuildRepresentation(double input, bool hasSpace, bool useSymbol, int? decimals)
{
var exponent = (int)Math.Floor(Math.Log10(Math.Abs(input)) / 3);
return exponent.Equals(0)
return exponent.Equals(0)
? input.ToString()
: BuildMetricRepresentation(input, exponent, hasSpace, useSymbol);
: BuildMetricRepresentation(input, exponent, hasSpace, useSymbol, decimals);
}

/// <summary>
Expand All @@ -221,10 +224,13 @@ private static string BuildRepresentation(double input, bool hasSpace, bool useS
/// <param name="exponent">Exponent of the number in a scientific notation</param>
/// <param name="hasSpace">True will split the number and the symbol with a whitespace.</param>
/// <param name="useSymbol">True will use symbol instead of name</param>
/// <param name="decimals">If not null it is the numbers of decimals to round the number to</param>
/// <returns>A number in a Metric representation</returns>
private static string BuildMetricRepresentation(double input, int exponent, bool hasSpace, bool useSymbol)
private static string BuildMetricRepresentation(double input, int exponent, bool hasSpace, bool useSymbol, int? decimals)
{
var number = input * Math.Pow(1000, -exponent);
if (decimals.HasValue)
number = Math.Round(number, decimals.Value);
var symbol = Math.Sign(exponent) == 1
? Symbols[0][exponent - 1]
: Symbols[1][-exponent - 1];
Expand Down

0 comments on commit 283b233

Please sign in to comment.