我想用给定的双数返回它的“大小”(称为 |number|,或点后没有数字的位数),例如:
12.324654 -> 2
12 -> 2
0.99 -> 0
1.01 -> 1
901 -> 3
-0.99 -> 0
-9.999 -> 1
必须有一个功能是.net,我不熟悉它..
谢谢。
我想用给定的双数返回它的“大小”(称为 |number|,或点后没有数字的位数),例如:
12.324654 -> 2
12 -> 2
0.99 -> 0
1.01 -> 1
901 -> 3
-0.99 -> 0
-9.999 -> 1
必须有一个功能是.net,我不熟悉它..
谢谢。
尝试 log 10 (max(abs( number ), 0.5)) + 1 向下舍入。
或者,在实际的 C# 语法中:
(int)(Math.Log10(Math.Max(Math.Abs(number), 0.5)) + 1)
好的,它是如何工作的?
首先, p = log 10 ( x )是x的以 10 为底的对数;也就是说,10 的p次方(或 1 后跟 p 个零)等于x的值。对数本质上测量数字的长度,除了它是x的平滑函数:
(请注意,在不提供以 10 为底的对数函数的语言中,我们始终可以将其计算为 log 10 ( x ) = log( x ) / log(10),其中 log() 是任意函数中的对数函数根据。)
例如,我们有
日志10 (1) = 0.0
日志10 (10) = 1.0
日志10 (100) = 2.0
日志10 (1000) = 3.0
但也如:
日志10 (5) = 0.69897
日志10 (50) = 1.69897
日志10 (500) = 2.69897
日志10 (5000) = 3.69897
通常, 只要 10 n ≤ x < 10 n +1 , n ≤ log 10 ( x ) < n +1。
查看上面的值,应该很容易看出,要获得整数中以 10 为底的位数,我们应该将其以 10 为底的对数向下舍入到最接近的整数并加 1(因为我们想要10 的长度为 2,而不是 1)。
但是,还有一些边缘情况需要考虑:
首先,最初的提问者希望 - x的长度等于x的长度。对数仅针对正数定义,因此我们将x替换为其绝对值以使其始终为正数。
其次,最初的提问者还希望 0 和 1 之间的数字长度为零。然而,对数可以取任意大的负值:
log 10 (0.1) = -1.0
log 10 (0.01) = -2.0
log 10 (0.001) = -3.0
log 10 (0.0001) = -4.0
事实上,log 10 (0) = -∞。为了满足这个要求,我们只需使用它的最大值和 0.5 作为 log 10 ()的输入,确保我们计算的长度永远不会低于 0.5 。(我们可以使用 0.1 到 1 之间的任何数字作为截止值,但 0.5 恰好是一个很好的圆形二进制分数。)
此外,我们必须确保在四舍五入之前对数加上 +1 ,以便我们四舍五入的数字始终为非负数。这是因为(int)
在 C# 中实际上将负数向上舍入为零。例如,由于 log 10 (0.5) ≈ −0.3,表达式(int)Math.Log10(0.5) + 1
(加法前舍入)将计算为 0+1 = 1,而不是预期的 0。
((int)Math.Abs(12.324654)).ToString().Length
Math.Abs
将转换为正数(不想计算负号)
(int)
将删除小数点后面的数字
ToString()
转换为字符串 ===> "12"
Length
告诉您有多少个字符存在
边缘情况 where (int)( some number ) == 0
, where长度会给你 1——你可能不想要这个,所以要注意这种可能性
现在,您可以做的就是将此作为扩展方法....
public static class Utils
{
public static int Size(this double n)
{
int i = (int)Math.Abs(n);
if ( i == 0 ) return 0;
return i.ToString().Length;
}
}
12.324654.Size() == 2;
您可以执行以下操作来说明您的0
数字返回零长度
private static int CountAbsoluteDigits(double p) {
int absolute = (int)Math.Abs(p);
if (0 == absolute)
return 0;
else
return absolute.ToString().Length;
}
...
var length = CountAbsoluteDigits(12.324654);
这是我用你提供的数字得到的输出..
12.324654 -> 2
12 -> 2
0.99 -> 0
1.01 -> 1
901 -> 3
-0.99 -> 0
-9.999 -> 1
窃取 Quintin 的格式:
private static int CountAbsoluteDigits(double p) {
int ip = (int)p;
int answer = 0;
while (ip!=0) {
answer++;
ip/=10;
}
return answer;
}
在此不需要任何技巧(例如,, abs()
)if
。
Courtsey Muad'Dib
int GetLength(double value){
return ((int)Math.Abs(value*10d)).ToString().Length - 1
}
仅当值在 int 范围内时,转换为整数并将结果转换为字符串才有效。如果您需要超过 20 亿的值,则需要使用日志,或者将双精度值转换为字符串。
static int GetLength(double d)
{
d = Math.Abs(d);
if (d < 1.0) return 0;
if (double.IsInfinity(d)) return int.MaxValue;
if (double.IsNaN(d)) return 0;
return (int)Math.Floor(Math.Log10(d)) + 1;
}
static int GetLength2(double d)
{
d = Math.Abs(d);
if (d < 1.0) return 0;
if (double.IsInfinity(d)) return int.MaxValue;
if (double.IsNaN(d)) return 0;
string s = d.ToString("E"); // returns a string in the format "1.012435E+001"
return int.Parse(s.Substring(s.Length - 3)) + 1;
}
static void Test(double d) { Debug.WriteLine(d + " -> " + GetLength(d) + ", " + GetLength2(d)); }
static void Main(string[] args)
{
Test(0);
Test(0.125);
Test(0.25);
Test(0.5);
Test(1);
Test(2);
Test(10);
Test(10.5);
Test(10.25);
Test(10.1243542354235623542345234523452354);
Test(999999);
Test(1000000);
Test(1000001);
Test(999999.111);
Test(1000000.111);
Test(1000001.111);
Test(double.MaxValue);
Test(double.MinValue);
Test(double.PositiveInfinity);
Test(double.NegativeInfinity);
Test(double.NaN);
Test(double.Epsilon);
}
结果:
0 -> 0, 0
0.125 -> 0, 0
0.25 -> 0, 0
0.5 -> 0, 0
1 -> 1, 1
2 -> 1, 1
10 -> 2, 2
10.5 -> 2, 2
10.25 -> 2, 2
10.1243542354236 -> 2, 2
999999 -> 6, 6
1000000 -> 7, 7
1000001 -> 7, 7
999999.111 -> 6, 6
1000000.111 -> 7, 7
1000001.111 -> 7, 7
1.79769313486232E+308 -> 309, 309
-1.79769313486232E+308 -> 309, 309
Infinity -> 2147483647, 2147483647
-Infinity -> 2147483647, 2147483647
NaN -> 0, 0
4.94065645841247E-324 -> 0, 0