一种c#格式提供程序,它使用工程表示法规则将双重格式格式化为字符串。如果该值在定义的符号之外,它将默认使用科学符号。
我编写这段代码是为了更好地处理以前处理遗留项目的工程符号格式的乱糟糟的case语句。该项目预先对被测试的产品进行电气测量,例如电压、电流和电阻。如果用工程符号表示,这些测量对测试技术人员来说要容易得多。
class EngNotationFormatter : IFormatProvider, ICustomFormatter
{
private readonly Dictionary notationSymbols = new Dictionary
{
{double.NegativeInfinity, ""},
{-24, "y"},
{-21, "z"},
{-18, "a"},
{-15, "f"},
{-12, "p"},
{-9, "n"},
{-6, "μ"},
{-3, "m"},
{0, ""},
{3, "k"},
{6, "M"},
{9, "G"},
{12, "T"},
{15, "P"},
{18, "E"},
{21, "Z"},
{24, "Y"},
};
public string Format(string format, object arg, IFormatProvider formatProvider)
{
double value = Convert.ToDouble(arg);
double exponent = Math.Log10(Math.Abs(value));
double engExponent = Math.Floor(exponent / 3) * 3;
string symbol = notationSymbols.ContainsKey(engExponent) ? notationSymbols[engExponent] : "e" + engExponent;
return (value * Math.Pow(10, -(int)engExponent)).ToString("0.########") + symbol;
}
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
else
return null;
}
}示例使用:
Console.WriteLine(String.Format(new EngNotationFormatter(), "{0}Ω", 0.01234)); //result: 12.34mΩ原始case语句是在代码中放置的,这里的dat是要格式化的两个,精度是要显示的数字数(这个值总是相同的)。
Function formatData(ByVal dat As Single, ByVal precision As String) As String
Select Case System.Math.Abs(dat)
Case 0
formatData = "0"
Case Is < 0.000000000001
formatData = Format(dat * 1.0E+15, precision & "f")
Case Is < 0.000000001
formatData = Format(dat * 1000000000000.0#, precision & "p")
Case Is < 0.000001
formatData = Format(dat * 1000000000.0#, precision & "n")
Case Is < 0.001
formatData = Format(dat * 1000000.0#, precision & "u")
Case Is < 0.99
formatData = Format(dat * 1000.0#, precision & "m")
'Case Is < 1101#
Case Is < 1000.0#
formatData = Format(dat, precision & "")
Case Is < 1000000.0#
formatData = Format(dat / 1000.0#, precision & "k")
Case Is < 1000000000.0#
formatData = Format(dat / 1000000.0#, precision & "M")
Case Is < 1000000000000.0#
formatData = Format(dat / 1000000000.0#, precision & "G")
Case Else
formatData = ""
End Select
End Function发布于 2022-07-14 20:51:16
我不知道您为什么选择使用IFormatProvider,以及为什么手动添加使用string.Format的符号。
尽管如此,如果您使用notationSymbols来避免不必要的内存分配,那么使用switch会更好。如果您正在计划扩展它,或者您不认为switch很适合您的用例,那么请保留它,但也要缓存它以供重用。
double value = Convert.ToDouble(arg);如果arg不是有效整数(例如null),这将引发一个exception.So,相反,您可以这样做:
if(arg is double value)
{
// code
}或者这个:
if(double.TryParse(arg?.ToString(), out var value))
{
// code
}最后一个注意事项是,当从较低的精度转换到更高的精度时,需要确保它们之间的值一致性,这是一个非常常见的问题。所以,有一个计划来确保旧的精确性和新的精确性之间的兼容性,就可以保证你的麻烦。
最后,您可以实现一个用于符号的抽象类,而不是实现IFormatProvider,然后使用扩展方法来格式化数字。
例子:
public abstract class EngineeringNotation
{
private readonly char _notationSymbol;
protected EngineeringNotation(char notationSymbol) {
_notationSymbol = notationSymbol;
}
public string Format(double number)
{
double exponent = Math.Log10(Math.Abs(number));
double engExponent = Math.Floor(exponent / 3) * 3);
double result = number * Math.Pow(10, -(int)engExponent);
string symbol = GetSymbol(engExponent);
return $"{result:0.########}{symbol}{_notationSymbol}";
}
private static string GetSymbol(double exponent)
{
switch (exponent)
{
case double.NegativeInfinity:
case 0:
return string.Empty;
case -24:
return "y";
case -21:
return "z";
case -18:
return "a";
case -15:
return "f";
case -12:
return "p";
case -9:
return "n";
case -6:
return "μ";
case -3:
return "m";
case 3:
return "k";
case 6:
return "M";
case 9:
return "G";
case 12:
return "T";
case 15:
return "P";
case 18:
return "E";
case 21:
return "Z";
case 24:
return "Y";
default:
return $"e{exponent}";
}
}
}
public class VoltNotation : EngineeringNotation
{
public VoltNotation() : base('V') { }
}
public class OhmNotation : EngineeringNotation
{
public OhmNotation() : base('Ω') { }
}
public static class NotationExtensions
{
public static string FormatNotation(this double value, EngineeringNotation notation)
{
return notation.Format(value);
}
public static string FormatAsVoltNotation(this double value)
{
return FormatNotation(value, new VoltNotation());
}
public static string FormatAsOhmNotation(this double value)
{
return FormatNotation(value, new OhmNotation());
}
}现在你可以这样做了:
double number = 0.01234;
string formated = number.FormatAsOhmNotation();https://codereview.stackexchange.com/questions/278074
复制相似问题