-
Notifications
You must be signed in to change notification settings - Fork 387
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
Dynamic Unit Selection #831
Comments
Hi and thanks for the suggestion. We already have the following convention Output:
LINQPad example: void Main()
{
var a = Information.FromMegabits(2100).Dump();
var b = Information.FromMegabytes(2100).Dump();
var c = Information.FromMebibits(2148).Dump();
var d = Information.FromMebibytes(2148).Dump();
// From this
Console.WriteLine("\nToUnit:");
a.ToUnit(InformationUnit.Gigabit).ToString().Dump();
b.ToUnit(InformationUnit.Gigabyte).ToString().Dump();
c.ToUnit(InformationUnit.Gibibit).ToString().Dump();
d.ToUnit(InformationUnit.Gibibyte).ToString().Dump();
// To this
Console.WriteLine("\nToOptimalUnit (inferred binary multiple):");
a.ToOptimalUnit().ToString().Dump();
b.ToOptimalUnit().ToString().Dump();
c.ToOptimalUnit().ToString().Dump();
d.ToOptimalUnit().ToString().Dump();
// Or this
Console.WriteLine("\nToOptimalUnit (explicit binary multiple):");
a.ToOptimalUnit(BinaryMultiple.Bit1000).ToString().Dump();
b.ToOptimalUnit(BinaryMultiple.Byte1000).ToString().Dump();
c.ToOptimalUnit(BinaryMultiple.Bit1024).ToString().Dump();
d.ToOptimalUnit(BinaryMultiple.Byte1024).ToString().Dump();
}
public enum BinaryMultiple
{
Bit1000,
Bit1024,
Byte1000,
Byte1024
}
// Define other methods and classes here
public static class MyExtensions
{
public static Information ToOptimalUnit(this Information x, BinaryMultiple binaryMultiple)
{
InformationUnit GetOptimalUnit()
{
switch (binaryMultiple)
{
case BinaryMultiple.Bit1000:
{
var log10 = Math.Log10(Convert.ToDouble(x.ToUnit(InformationUnit.Bit).Value));
if (log10 < 3) return InformationUnit.Bit;
if (log10 < 6) return InformationUnit.Kilobit;
if (log10 < 9) return InformationUnit.Megabit;
if (log10 < 12) return InformationUnit.Gigabit;
if (log10 < 15) return InformationUnit.Terabit;
if (log10 < 18) return InformationUnit.Exabit;
throw new ArgumentOutOfRangeException("Value", x.Value.ToString());
}
case BinaryMultiple.Byte1000:
{
var log10 = Math.Log10(Convert.ToDouble(x.ToUnit(InformationUnit.Byte).Value));
if (log10 < 3) return InformationUnit.Byte;
if (log10 < 6) return InformationUnit.Kilobyte;
if (log10 < 9) return InformationUnit.Megabyte;
if (log10 < 12) return InformationUnit.Gigabyte;
if (log10 < 15) return InformationUnit.Terabyte;
if (log10 < 18) return InformationUnit.Exabyte;
throw new ArgumentOutOfRangeException("Value", x.Value.ToString());
}
case BinaryMultiple.Bit1024:
{
var log10 = Math.Log10(Convert.ToDouble(x.ToUnit(InformationUnit.Bit).Value));
if (log10 < 6) return InformationUnit.Kibibit;
if (log10 < 9) return InformationUnit.Mebibit;
if (log10 < 12) return InformationUnit.Gibibit;
if (log10 < 15) return InformationUnit.Tebibit;
if (log10 < 18) return InformationUnit.Exbibit;
throw new ArgumentOutOfRangeException("Value", x.Value.ToString());
}
case BinaryMultiple.Byte1024:
{
var log10 = Math.Log10(Convert.ToDouble(Convert.ToDouble(x.ToUnit(InformationUnit.Bit).Value)));
if (log10 < 6) return InformationUnit.Kibibyte;
if (log10 < 9) return InformationUnit.Mebibyte;
if (log10 < 12) return InformationUnit.Gibibyte;
if (log10 < 15) return InformationUnit.Tebibyte;
if (log10 < 18) return InformationUnit.Exbibyte;
throw new ArgumentOutOfRangeException("Value", x.Value.ToString());
}
default:
throw new ArgumentOutOfRangeException("Unit", x.Unit.ToString());
}
}
return x.ToUnit(GetOptimalUnit());
}
// Tries to infer the binary multiple based on the unit.
public static Information ToOptimalUnit(this Information x)
{
BinaryMultiple GetInferredBinaryMultiple()
{
switch (x.Unit)
{
case InformationUnit.Bit:
case InformationUnit.Kilobit:
case InformationUnit.Megabit:
case InformationUnit.Gigabit:
case InformationUnit.Terabit:
case InformationUnit.Exabit:
return BinaryMultiple.Bit1000;
case InformationUnit.Byte:
case InformationUnit.Kilobyte:
case InformationUnit.Megabyte:
case InformationUnit.Gigabyte:
case InformationUnit.Terabyte:
case InformationUnit.Exabyte:
return BinaryMultiple.Byte1000;
case InformationUnit.Kibibit:
case InformationUnit.Mebibit:
case InformationUnit.Gibibit:
case InformationUnit.Tebibit:
case InformationUnit.Exbibit:
return BinaryMultiple.Bit1024;
case InformationUnit.Kibibyte:
case InformationUnit.Mebibyte:
case InformationUnit.Gibibyte:
case InformationUnit.Tebibyte:
case InformationUnit.Exbibyte:
return BinaryMultiple.Byte1024;
default:
throw new ArgumentOutOfRangeException("Unit");
}
}
var binaryMultiple = GetInferredBinaryMultiple();
return ToOptimalUnit(x, binaryMultiple);
}
} |
I can take a look however it's unlikely I will have time to spin it into a proper PR. I am doing this for work and only have so much time in the day. If I can easily turn it into a PR I will otherwise I will just have to use a local extension method or library. I also have other considerations to worry about, for example I will have to back prop it into the data struct to minimise recalculation as I will need to redo the calculation quite often. |
Still not 100% sure if this lib is going to work out for me. After reading your code in more detail it was very close to what I needed. I cleaned it up for testing if the lib is good. Feel free to use it for a PR if you want, I couldn't even find the information code in the repo presumably because it's auto gen so I have no idea where it would ilve. Other concerns for a PR include unit testing and generalisation.
Note I also added an extra method to modify the variable in place. Example usages:
|
Added some handling for bitrates, close to copy/paste. It can almost certainly be written more efficiently but I don't have the time or need for anything better.
Up to you @angularsen if you want to close this issue, I personally have what I need with the above code. Thank you for the help. |
Thanks for the update. I might merge this in at some point, it seems useful enough. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Is your feature request related to a problem? Please describe.
I would like to take a unit and write it with the simplest unit available. I.E. 1000mb should become 1gb. Ideally with 1024 bit division support. Very sorry if this is already a feature and I missed it, seems hard to believe nobody needed this before
Describe the solution you'd like
An overload of tostring or perhaps another function that finds the best unit before conversion. For mb it would require a concept of bits and bytes as it some cases I wish to show 1 or the other.
Another option is to take a unit and to provide a function to set the optimal base unit
Describe alternatives you've considered
We currently use a custom conversion system which is messy, I am hoping UnitsNet will do much better however without this vital feature it's, unfortunately, effectively useless to us. So sticking with that is the current alternative.
Additional context
An example:
The text was updated successfully, but these errors were encountered: