-
Notifications
You must be signed in to change notification settings - Fork 965
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
Measure of length #775
Open
JonasBarka
wants to merge
13
commits into
Humanizr:main
Choose a base branch
from
JonasBarka:fixesIssue526
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Measure of length #775
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
9ba6fc1
Updated public API. Started implenting #526. Fixed some grammar.
JonasBarka 6b83121
Basic implementation of #526 with tests.
JonasBarka 822a0aa
Renamed an existing method parameter for clarity.
JonasBarka 014efec
Added support for fractional prefixes to largestPrefix option.
JonasBarka e70b705
Added enum MetricPrefix, containing all supported metric prefixes and…
JonasBarka afe0ef2
Added default to MetricPrefix. Updated ToMetric to use MetricPrefix. …
JonasBarka 2ab9bd6
Added support for actual upper limit of MetricPrefix.None. Added Met…
JonasBarka 2386e96
Changed parameter name to maxPrefix.
JonasBarka 03e1f8d
Added nonfunctional minPrefix "stub", in fututre versions mirroring t…
JonasBarka 2fe1c46
Added functionality for "minPrefix". Interaction with "decimals" migh…
JonasBarka 1b029b5
Updated readme with current as well as new options.
JonasBarka 04d611c
Added examples to readme.
JonasBarka f1ef468
Updated copyright notice, minor readme and test comments changes.
JonasBarka File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
// Wrote by Alois de Gouvello https://github.com/aloisdg | ||
// Written by Alois de Gouvello https://github.com/aloisdg with additions by Jonas Barkå https://github.com/JonasBarka. | ||
|
||
// The MIT License (MIT) | ||
|
||
// Copyright (c) 2015 Alois de Gouvello | ||
// Copyright (c) 2015-2019 Alois de Gouvello and each other contributor for their respective work. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above |
||
// Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
// this software and associated documentation files (the "Software"), to deal in | ||
|
@@ -101,17 +101,19 @@ public static double FromMetric(this string input) | |
/// <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> | ||
/// <param name="maxPrefix">Largest metric prefix used in result.</param> | ||
/// <example> | ||
/// <code> | ||
/// 1000.ToMetric() => "1k" | ||
/// 123.ToMetric() => "123" | ||
/// 1E-1.ToMetric() => "100m" | ||
/// 1_000_000.ToMetric(largestPrefix = MetricPrefix.Kilo) => "1000k" | ||
/// </code> | ||
/// </example> | ||
/// <returns>A valid Metric representation</returns> | ||
public static string ToMetric(this int input, bool hasSpace = false, bool useSymbol = true, int? decimals = null) | ||
public static string ToMetric(this int input, bool hasSpace = false, bool useSymbol = true, int? decimals = null, MetricPrefix maxPrefix = MetricPrefix.Undefined, MetricPrefix minPrefix = MetricPrefix.Undefined) | ||
{ | ||
return ((double)input).ToMetric(hasSpace, useSymbol, decimals); | ||
return ((double)input).ToMetric(hasSpace, useSymbol, decimals, maxPrefix); | ||
} | ||
|
||
/// <summary> | ||
|
@@ -125,15 +127,17 @@ public static string ToMetric(this int input, bool hasSpace = false, bool useSym | |
/// <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> | ||
/// <param name="maxPrefix">Largest metric prefix used in result.</param> | ||
/// <example> | ||
/// <code> | ||
/// 1000d.ToMetric() => "1k" | ||
/// 123d.ToMetric() => "123" | ||
/// 1E-1.ToMetric() => "100m" | ||
/// 1_000_000.ToMetric(largestPrefix = MetricPrefix.Kilo) => "1000k" | ||
/// </code> | ||
/// </example> | ||
/// <returns>A valid Metric representation</returns> | ||
public static string ToMetric(this double input, bool hasSpace = false, bool useSymbol = true, int? decimals = null) | ||
public static string ToMetric(this double input, bool hasSpace = false, bool useSymbol = true, int? decimals = null, MetricPrefix maxPrefix = MetricPrefix.Undefined, MetricPrefix minPrefix = MetricPrefix.Undefined) | ||
{ | ||
if (input.Equals(0)) | ||
{ | ||
|
@@ -145,7 +149,7 @@ public static string ToMetric(this double input, bool hasSpace = false, bool use | |
throw new ArgumentOutOfRangeException(nameof(input)); | ||
} | ||
|
||
return BuildRepresentation(input, hasSpace, useSymbol, decimals); | ||
return BuildRepresentation(input, hasSpace, useSymbol, decimals, maxPrefix, minPrefix); | ||
} | ||
|
||
/// <summary> | ||
|
@@ -217,40 +221,74 @@ private static string ReplaceNameBySymbol(string input) | |
/// <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> | ||
/// <param name="maxPrefix">Largest metric prefix used in result.</param> | ||
/// <returns>A number in a Metric representation</returns> | ||
private static string BuildRepresentation(double input, bool hasSpace, bool useSymbol, int? decimals) | ||
private static string BuildRepresentation(double input, bool hasSpace, bool useSymbol, int? decimals, MetricPrefix maxPrefix, MetricPrefix minPrefix) | ||
{ | ||
var exponent = (int)Math.Floor(Math.Log10(Math.Abs(input)) / 3); | ||
return exponent.Equals(0) | ||
? input.ToString() | ||
: BuildMetricRepresentation(input, exponent, hasSpace, useSymbol, decimals); | ||
: BuildMetricRepresentation(input, exponent, hasSpace, useSymbol, decimals, maxPrefix, minPrefix); | ||
} | ||
|
||
/// <summary> | ||
/// Build a Metric representation of the number. | ||
/// </summary> | ||
/// <param name="input">Number to convert to a Metric representation.</param> | ||
/// <param name="exponent">Exponent of the number in a scientific notation</param> | ||
/// <param name="numericPrefix">Metric prefix expressed as a number.</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> | ||
/// <param name="maxPrefix">Largest metric prefix used in result.</param> | ||
/// <param name="minPrefix">Smallest metric prefix used in result.</param> | ||
/// <returns>A number in a Metric representation</returns> | ||
private static string BuildMetricRepresentation(double input, int exponent, bool hasSpace, bool useSymbol, int? decimals) | ||
private static string BuildMetricRepresentation(double input, int numericPrefix, bool hasSpace, bool useSymbol, int? decimals, MetricPrefix maxPrefix, MetricPrefix minPrefix) | ||
{ | ||
var number = input * Math.Pow(1000, -exponent); | ||
numericPrefix = numericPrefix.Clamp(minPrefix, maxPrefix); | ||
|
||
if (numericPrefix == 0) | ||
return input.ToString(); | ||
|
||
var number = input * Math.Pow(1000, -numericPrefix); | ||
|
||
if (decimals.HasValue) | ||
{ | ||
number = Math.Round(number, decimals.Value); | ||
} | ||
|
||
var symbol = Math.Sign(exponent) == 1 | ||
? Symbols[0][exponent - 1] | ||
: Symbols[1][-exponent - 1]; | ||
var symbol = Math.Sign(numericPrefix) == 1 | ||
? Symbols[0][numericPrefix - 1] | ||
: Symbols[1][-numericPrefix - 1]; | ||
|
||
return number | ||
+ (hasSpace ? " " : string.Empty) | ||
+ GetUnit(symbol, useSymbol); | ||
} | ||
|
||
/// <summary> | ||
/// Clamps a numeric representation of metric prefix. | ||
/// </summary> | ||
/// <param name="numericPrefix">Metric prefix, expressed as a number, to limit.</param> | ||
/// <param name="minPrefix">Lower limit.</param> | ||
/// <param name="maxPrefix">Upper limit.</param> | ||
/// <returns>Clamped numeric prefix representation</returns> | ||
private static int Clamp(this int numericPrefix, MetricPrefix minPrefix, MetricPrefix maxPrefix) | ||
{ | ||
if (maxPrefix == MetricPrefix.Undefined && minPrefix == MetricPrefix.Undefined) | ||
return numericPrefix; | ||
|
||
if (maxPrefix != MetricPrefix.Undefined && minPrefix != MetricPrefix.Undefined && maxPrefix < minPrefix) | ||
throw new ArgumentException($"{nameof(maxPrefix)} can't be smaller than {nameof(minPrefix)}."); | ||
|
||
var maxNumericPrefix = (int)maxPrefix / 3; | ||
var minNumericPrefix = (int)minPrefix / 3; | ||
|
||
if (maxPrefix != MetricPrefix.Undefined && maxNumericPrefix < numericPrefix) | ||
return maxNumericPrefix; | ||
else if (minPrefix != MetricPrefix.Undefined && minNumericPrefix > numericPrefix) | ||
return minNumericPrefix; | ||
else | ||
return numericPrefix; | ||
} | ||
|
||
/// <summary> | ||
/// Get the unit from a symbol of from the symbol's name. | ||
/// </summary> | ||
|
@@ -265,7 +303,7 @@ private static string GetUnit(char symbol, bool useSymbol) | |
/// <summary> | ||
/// Check if a Metric representation is out of the valid range. | ||
/// </summary> | ||
/// <param name="input">A Metric representation who might be out of the valid range.</param> | ||
/// <param name="input">A Metric representation that may be out of the valid range.</param> | ||
/// <returns>True if input is out of the valid range.</returns> | ||
private static bool IsOutOfRange(this double input) | ||
{ | ||
|
@@ -283,7 +321,7 @@ private static bool IsOutOfRange(this double input) | |
/// <remarks> | ||
/// ToDo: Performance: Use (string input, out number) to escape the double use of Parse() | ||
/// </remarks> | ||
/// <param name="input">A string who might contain a invalid Metric representation.</param> | ||
/// <param name="input">A string that may contain an invalid Metric representation.</param> | ||
/// <returns>True if input is not a valid Metric representation.</returns> | ||
private static bool IsInvalidMetricNumeral(this string input) | ||
{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
namespace Humanizer | ||
{ | ||
/// <summary> | ||
/// MetricPrefix contains all supported metric prefixes and their corresponding powers of ten as underlying values. | ||
/// </summary> | ||
/// <remarks> | ||
/// "None" represents no prefix, use "Undefined" as null equivalent. | ||
/// Unsupported values: hecto, deca, deci and centi. | ||
/// </remarks> | ||
public enum MetricPrefix | ||
{ | ||
Undefined = -100, | ||
Yocto = -24, | ||
Zepto = -21, | ||
Atto = -18, | ||
Femto = -15, | ||
Pico = -12, | ||
Nano = -9, | ||
Micro = -6, | ||
Milli = -3, | ||
None = 0, | ||
Kilo = 3, | ||
Mega = 6, | ||
Giga = 9, | ||
Tera = 12, | ||
Peta = 15, | ||
Exa = 18, | ||
Zetta = 21, | ||
Yotta = 24 | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The copyrights at the top of the file, if any, should be simply
Copyright (c) .NET Foundation and Contributors
Alternatively, it can be removed as it's in the project root.