Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding parameter decimals toMetric(). Fixes #609 #610

Merged
merged 1 commit into from
Apr 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -388,8 +388,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