我试图获取以下双精度值中的位数:56.46855976,而不使用将其转换为字符串(只需将“.”替换为“”)。
有人有什么想法吗?
计算必须将数字除以 10 的次数,直到它小于 1 -> 这样就可以得到小数点前的数字。
然后计算您必须将原始数字乘以 10 的次数,直到它等于 Math.Floor-result ->,它给出了小数点后面的数字。
添加。高兴就好。
编辑:正如乔伊指出的那样,其中存在一些不确定性。预先定义最大位数,这样就不会创建无限循环。 另一方面 - “丹麦的海岸有多长?”...
/// Returns how many digits there are to the left of the .
public static int CountDigits(double num) {
int digits = 0;
while (num >= 1) {
digits++;
num /= 10;
}
return digits;
}
正如 Martin 提到的,数到 .毫无意义。
测试:
MathPlus.CountDigits(56.46855976) -> 2
MathPlus.CountDigits((double)long.MaxValue + 1) -> 19
MathPlus.CountDigits(double.MaxValue) -> 309
转换为字符串可能是最好的选择。请记住,
double
s 在内部以 Base 2 表示。因此,您看到的十进制表示形式只是实际存储值的近似值(最大 253 的整数除外),即 2 的各个幂的总和。
因此,尝试从二进制表示中算出十进制位数肯定不是一项简单或微不足道的任务 - 特别是因为该框架还可能应用舍入来使像 3.999999999998 这样的数字看起来像 4.0,因为它们看起来比实际具有更高的精度是。
对于“右侧数字”(即数字“顺序”),在任何静态类中添加此扩展方法:
public static int GetDigitsCount(this double value) =>
value == double.NaN ? 0 : (int)Math.Log10(value) + 1;
对于更一般的情况:“右侧数字”和“左侧数字”(定义为有效数字的数量,即最低的非零小数位):
public static int GetDigitsCount(this double value, bool leftSide = true)
{
if (value == double.NaN) return 0;
if (leftSide) return (int)Math.Log10(value) + 1
int significantDigits = 0;
while (Math.Abs(value - Math.Round(value, significantDigits)) > 2 * Double.Epsilon)
significantDigits++;
return significantDigits;
}
测试:
130.23.GetDigitsCount() -> returns 3
130.23.GetDigitsCount(false) -> returns 2