这比乍看起来要复杂得多。你需要考虑:
- 小数点包含在字符串长度中
- 如果没有小数的字符串表示超过最大长度,则输入无效,但是...
- 如果字符串表示仅超过带小数的最大长度,则可以简单地四舍五入
我的解决方案:
public string GetString(CultureInfo culture) {
var integral = (int)Math.Truncate(Value);
var integralLength = integral.ToString().Length;
if (integralLength > MaxLength) {
throw new InvalidOperationException();
}
var integralWithDecimalSeparatorLength = integralLength + culture.NumberFormat.NumberDecimalSeparator.Length;
var minimumFixedPointLength = integralWithDecimalSeparatorLength + 1;
if (minimumFixedPointLength > MaxLength) {
var intValue = (int)Math.Round(Value);
return intValue.ToString("D" + MinLength, culture);
}
var precision = MaxLength - integralWithDecimalSeparatorLength;
return Value.ToString("F" + precision, culture);
}
首先,如果值的整数部分(不包括小数)太长,则值太大。否则,用于定点 ("F") 字符串格式的精度是根据剩余可用空间计算的。如果没有足够的空间,则使用四舍五入的整数。定点格式的最小长度是整数、小数点和一个小数位(总是至少有一个,它不会格式化为一个尾随小数点)。
使用MinLength=4
,MaxLength=4
和Value=954
, 输出是"0954"
, 但使用Value=54
, 是"54.0"
因为有足够的空间.0
. 这也将支持小数点分隔符长度超过一个字符的文化,尽管我不确定是否真的存在。
更多示例:
Value=987.654
, MinLength=4
, MaxLength=4
:"0988"
Value=987.654
, MinLength=3
, MaxLength=4
:"988"
Value=987.654
, MinLength=4
, MaxLength=5
:"987.7"
Value=987.654
, MinLength=4
, MaxLength=10
:"987.654000"