我正在尝试确定c#ulong数字中的位数,我试图使用一些数学逻辑而不是使用ToString()。长度。我没有对这两种方法进行基准测试,但已经看到有关使用System.Math.Floor(System.Math.Log10(number))+ 1来确定位数的其他帖子。 似乎工作正常,直到我从999999999999997过渡到999999999999998,此时,我开始得到一个不正确的计数。
之前有没有人遇到过这个问题?
我见过类似帖子的Java重点@ Why log(1000)/log(10) isn't the same as log10(1000)?以及帖子@ How to get the separate digits of an int number?,它表示我怎么可能使用%运算符实现相同但有更多代码
这是我用来模拟这个
的代码Action<ulong> displayInfo = number =>
Console.WriteLine("{0,-20} {1,-20} {2,-20} {3,-20} {4,-20}",
number,
number.ToString().Length,
System.Math.Log10(number),
System.Math.Floor(System.Math.Log10(number)),
System.Math.Floor(System.Math.Log10(number)) + 1);
Array.ForEach(new ulong[] {
9U,
99U,
999U,
9999U,
99999U,
999999U,
9999999U,
99999999U,
999999999U,
9999999999U,
99999999999U,
999999999999U,
9999999999999U,
99999999999999U,
999999999999999U,
9999999999999999U,
99999999999999999U,
999999999999999999U,
9999999999999999999U}, displayInfo);
Array.ForEach(new ulong[] {
1U,
19U,
199U,
1999U,
19999U,
199999U,
1999999U,
19999999U,
199999999U,
1999999999U,
19999999999U,
199999999999U,
1999999999999U,
19999999999999U,
199999999999999U,
1999999999999999U,
19999999999999999U,
199999999999999999U,
1999999999999999999U
}, displayInfo);
提前致谢
专利
答案 0 :(得分:7)
log10将涉及浮点转换 - 因此舍入错误。对于double来说,误差非常小,但对于精确整数来说这是一个大问题!
排除.ToString()方法和浮点方法,然后是,我认为你将不得不使用迭代方法,但我会使用整数除法而不是模数。
整数除以10.结果是&gt; 0?如果是这样的话。如果没有,停止。 位数是所需的迭代次数。
EG。 5 - &gt; 0; 1次迭代= 1位数。
1234 - &gt; 123 - &gt; 12 - &gt; 1 - &gt; 0; 4次迭代= 4位数。
答案 1 :(得分:6)
我会使用ToString().Length
,除非你知道这将被召唤数百万次。
答案 2 :(得分:3)
默认情况下,Double值包含15 但精度的十进制数字 最多保留17位数字 内部。
我怀疑你正在达到精确限制。您的值999,999,999,999,998可能处于精度限制。由于在调用ulong
之前必须将double
转换为Math.Log10
,因此您会看到此错误。
答案 3 :(得分:0)
其他答案已经发布为什么会发生这种情况。
这是一个确定整数“长度”的快速方法示例(某些情况除外)。这本身并不是很有趣 - 但是我把它包含在这里因为使用这个方法与Log10 结合使用可以获得无条件长整个范围的“完美”精度,而无需第二次日志调用
// the lookup would only be generated once
// and could be a hard-coded array literal
ulong[] lookup = Enumerable.Range(0, 20)
.Select((n) => (ulong)Math.Pow(10, n)).ToArray();
ulong x = 999;
int i = 0;
for (; i < lookup.Length; i++) {
if (lookup[i] > x) {
break;
}
}
// i is length of x "in a base-10 string"
// does not work with "0" or negative numbers
这种查找表方法可以很容易地转换为任何基础。 这种方法应该比迭代的逐个分区方法更快,但是分析是留给读者的练习。 (直接if-then分支分成“组”可能更快,但这对我的口味来说太多重复键入。)
快乐的编码。