目标
由于浮点数有漂移问题,转成字符串时 3.6 有可能得到 3.6000000000001,总之很长的一串,通常需要截取,但按照固定长度截取不一定能使用各种情况,如果能根据数值大小保留有效位数就好了。
C#实现
我们可以在基础库里增加一个扩展类,给double, float 一个ToFixed 扩展方法,注意该类不要有命名空间,否则调用时还要加上 using 才能找到。
using System;
public static class DoubleExtensions
{
public static string ToFixed(this double d, int accLen = 3)
{
return toFixed(d, accLen);
}
public static string ToFixed(this float d, int accLen = 3)
{
return toFixed(d, accLen);
}
private static string toFixed(double d, int accLen)
{
var abs = Math.Abs(d);
if (abs == 0) return "0";
int fixedlen = accLen - (int)Math.Log10(abs);
fixedlen = Math.Max(0, fixedlen);
return d.ToString($"F{fixedlen}");
}
}
JavaScript实现
实现思路相同,需要的话可以封装一下再用。
var fixedlen = 0;
if (Math.abs(value) < 1000 && value !== 0)
fixedlen = 3 - Math.log(Math.abs(value)) / Math.LN10;
value = value.toFixed(fixedlen);
测试结果
取整
按照上述思路,C#中调用Math.Round即可实现智能取整。由于末端处理较为麻烦,我现在读到数据后就Round,后面就不用再ToFixed了。
public static string ToFixed(this float d, int accLen = 3)
{
return toFixed(d, accLen);
}
public static double Round(this float d, int accLen = 3)
{
return round(d, accLen);
}
private static double round(double d, int accLen)
{
var abs = Math.Abs(d);
if (abs == 0) return 0;
int fixedlen = accLen - (int)Math.Log10(abs);
fixedlen = Math.Max(0, fixedlen);
return Math.Round(d, fixedlen);
}