using System; namespace Cryville.Common { public struct Qualified : IFormattable where T : IConvertible { static readonly string _prefixes = "yzafpnμm kMGTPEZY"; public T Value { get; set; } public string Unit { get; set; } public Qualified(string unit) : this(default, unit) { } public Qualified(T value, string unit) { Value = value; Unit = unit; } public override readonly string ToString() { return ToString("G3"); } public readonly string ToString(string format) { return ToString(format, null); } public readonly string ToString(string format, IFormatProvider formatProvider) { double value = Value.ToDouble(formatProvider); int expIndex = (int)System.Math.Log10(value) / 3; if (expIndex == 0) { return value.ToString(format, formatProvider) + Unit; } int prefixIndex = System.Math.Clamp(expIndex + 8, 0, _prefixes.Length - 1); value /= System.Math.Pow(1e3, prefixIndex - 8); return value.ToString(format, formatProvider) + _prefixes[prefixIndex] + Unit; } } }