如何计算C#中数字的总位数?例如,数字887979789有9位数字。
答案 0 :(得分:139)
如果不转换为字符串,您可以尝试:
Math.Ceiling(Math.Log10(n));
ysap评论后的更正:
Math.Floor(Math.Log10(n) + 1);
答案 1 :(得分:68)
试试这个:
myint.ToString().Length
这有用吗?
答案 2 :(得分:20)
这些扩展中的任何一个都可以胜任:
public static class Int32Extensions
{
// THE MATHEMATICALLY FORMULATED ONE:
public static int Digits1(this Int32 n) =>
n == 0 ? 1 : 1 + (int) Math.Log10(Math.Abs(n));
// TYPICAL PROGRAMMING APPROACH:
public static int Digits2(this Int32 n)
{
int digits = 0;
do { ++digits; n /= 10; } while (n != 0);
return digits;
}
// THE UGLIEST POSSIBLE THING:
public static int Digits3(this Int32 n)
{
n = Math.Abs(n);
if (n < 10) return 1;
if (n < 100) return 2;
if (n < 1000) return 3;
if (n < 10000) return 4;
if (n < 100000) return 5;
if (n < 1000000) return 6;
if (n < 10000000) return 7;
if (n < 100000000) return 8;
if (n < 1000000000) return 9;
return 10;
}
// THE LOCOMOTIVE PULLING CHARACTERS:
public static int Digits4(this Int32 n) =>
n >= 0 ? n.ToString().Length : n.ToString().Length - 1;
}
我在5种不同的情况下对这些性能进行了一些性能测试,这些情况是使用Stopwatch
对for循环中的100.000.000次调用进行的。
胜利者是...
-1000000000.Digits1() => 1806 ms
-1000000000.Digits2() => 4114 ms
-1000000000.Digits3() => 664 ms <<<
-1000000000.Digits4() => 13600 ms
-1000.Digits1() => 1839 ms
-1000.Digits2() => 1163 ms
-1000.Digits3() => 429 ms <<<
-1000.Digits4() => 9959 ms
0.Digits1() => 166 ms <<<
0.Digits2() => 369 ms
0.Digits3() => 165 ms <<<
0.Digits4() => 7416 ms
1000.Digits1() => 1578 ms
1000.Digits2() => 1182 ms
1000.Digits3() => 328 ms <<<
1000.Digits4() => 9296 ms
1000000000.Digits1() => 1596 ms
1000000000.Digits2() => 4074 ms
1000000000.Digits3() => 581 ms <<<
1000000000.Digits4() => 13679 ms
最糟糕的事情!
答案 3 :(得分:12)
不直接使用C#,但公式为:n = floor(log10(x)+1)
答案 4 :(得分:7)
这里的答案适用于无符号整数,但我没有找到很好的解决方案来获取小数和双精度数字。
public static int Length(double number)
{
number = Math.Abs(number);
int length = 1;
while ((number /= 10) >= 1)
length++;
return length;
}
//number of digits in 0 = 1,
//number of digits in 22.1 = 2,
//number of digits in -23 = 2
如果精度很重要,您可以将输入类型从double
更改为decimal
,但十进制也有限制。
答案 5 :(得分:5)
使用递归(有时会在面试时询问)
public int CountDigits(int number)
{
// In case of negative numbers
number = Math.Abs(number);
if (number >= 10)
return CountDigits(number / 10) + 1;
return 1;
}
答案 6 :(得分:5)
Steve is correct的答案,但它对小于1的整数不起作用。
这是一个适用于否定的更新版本:
int digits = n == 0 ? 1 : Math.Floor(Math.Log10(Math.Abs(n)) + 1)
答案 7 :(得分:4)
static void Main(string[] args)
{
long blah = 20948230498204;
Console.WriteLine(blah.ToString().Length);
}
答案 8 :(得分:1)
将数字除以10将得到最左边的数字,然后对数字进行模数10给出没有第一个数字的数字并重复该数字直到你拥有所有数字
答案 9 :(得分:1)
这是使用二进制搜索的实现。看起来是迄今为止int32上最快的。
将Int64实现留给读者练习(!)
我尝试使用Array.BinarySearch而不是对树进行硬编码,但这只是速度的一半。
编辑: 查找表比二进制搜索快得多,但代价是要使用更多的内存。实际上,我可能会在生产环境中使用二进制搜索,因此查找表的速度增加了很多复杂性,可能会被软件的其他部分所掩盖。
org.mockito.ArgumentMatchers.isNull
查找表版本:
Lookup-Table: 439 ms
Binary-Search: 1069 ms
If-Chain: 1409 ms
Log10: 1145 ms
While: 1768 ms
String: 5153 ms
二进制搜索版本
static byte[] _0000llll = new byte[0x10000];
static byte[] _FFFFllll = new byte[0x10001];
static sbyte[] _hhhhXXXXdigits = new sbyte[0x10000];
// Special cases where the high DWORD is not enough information to find out how
// many digits.
static ushort[] _lowordSplits = new ushort[12];
static sbyte[] _lowordSplitDigitsLT = new sbyte[12];
static sbyte[] _lowordSplitDigitsGE = new sbyte[12];
static Int32Extensions()
{
// Simple lookup tables for number of digits where value is
// 0000xxxx (0 .. 65535)
// or FFFFxxxx (-1 .. -65536)
precomputePositiveLo16();
precomputeNegativeLo16();
// Hiword is a little more complex
precomputeHiwordDigits();
}
private static void precomputeHiwordDigits()
{
int b = 0;
for(int hhhh = 0; hhhh <= 0xFFFF; hhhh++)
{
// For hiword hhhh, calculate integer value for loword of 0000 and FFFF.
int hhhh0000 = (unchecked(hhhh * 0x10000)); // wrap around on negatives
int hhhhFFFF = hhhh0000 + 0xFFFF;
// How many decimal digits for each?
int digits0000 = hhhh0000.Digits_IfChain();
int digitsFFFF = hhhhFFFF.Digits_IfChain();
// If same number of decimal digits, we know that when we see that hiword
// we don't have to look at the loword to know the right answer.
if(digits0000 == digitsFFFF)
{
_hhhhXXXXdigits[hhhh] = (sbyte)digits0000;
}
else
{
bool negative = hhhh >= 0x8000;
// Calculate 10, 100, 1000, 10000 etc
int tenToThePower = (int)Math.Pow(10, (negative ? digits0000 : digitsFFFF) - 1);
// Calculate the loword of the 10^n value.
ushort lowordSplit = unchecked((ushort)tenToThePower);
if(negative)
lowordSplit = unchecked((ushort)(2 + (ushort)~lowordSplit));
// Store the split point and digits into these arrays
_lowordSplits[b] = lowordSplit;
_lowordSplitDigitsLT[b] = (sbyte)digits0000;
_lowordSplitDigitsGE[b] = (sbyte)digitsFFFF;
// Store the minus of the array index into the digits lookup. We look for
// minus values and use these to trigger using the split points logic.
_hhhhXXXXdigits[hhhh] = (sbyte)(-b);
b++;
}
}
}
private static void precomputePositiveLo16()
{
for(int i = 0; i <= 9; i++)
_0000llll[i] = 1;
for(int i = 10; i <= 99; i++)
_0000llll[i] = 2;
for(int i = 100; i <= 999; i++)
_0000llll[i] = 3;
for(int i = 1000; i <= 9999; i++)
_0000llll[i] = 4;
for(int i = 10000; i <= 65535; i++)
_0000llll[i] = 5;
}
private static void precomputeNegativeLo16()
{
for(int i = 0; i <= 9; i++)
_FFFFllll[65536 - i] = 1;
for(int i = 10; i <= 99; i++)
_FFFFllll[65536 - i] = 2;
for(int i = 100; i <= 999; i++)
_FFFFllll[65536 - i] = 3;
for(int i = 1000; i <= 9999; i++)
_FFFFllll[65536 - i] = 4;
for(int i = 10000; i <= 65535; i++)
_FFFFllll[65536 - i] = 5;
}
public static int Digits_LookupTable(this int n)
{
// Split input into low word and high word.
ushort l = unchecked((ushort)n);
ushort h = unchecked((ushort)(n >> 16));
// If the hiword is 0000 or FFFF we have precomputed tables for these.
if(h == 0x0000)
{
return _0000llll[l];
}
else if(h == 0xFFFF)
{
return _FFFFllll[l];
}
// In most cases the hiword will tell us the number of decimal digits.
sbyte digits = _hhhhXXXXdigits[h];
// We put a positive number in this lookup table when
// hhhh0000 .. hhhhFFFF all have the same number of decimal digits.
if(digits > 0)
return digits;
// Where the answer is different for hhhh0000 to hhhhFFFF, we need to
// look up in a separate array to tell us at what loword the change occurs.
var splitIndex = (sbyte)(-digits);
ushort lowordSplit = _lowordSplits[splitIndex];
// Pick the correct answer from the relevant array, depending whether
// our loword is lower than the split point or greater/equal. Note that for
// negative numbers, the loword is LOWER for MORE decimal digits.
if(l < lowordSplit)
return _lowordSplitDigitsLT[splitIndex];
else
return _lowordSplitDigitsGE[splitIndex];
}
答案 10 :(得分:0)
整数总位数:
double input = Convert.ToDouble(Console.ReadLine());
double b = Math.Floor(Math.Log10(input) + 1);
int c = Convert.ToInt32(b);
答案 11 :(得分:0)
创建一个返回所有数字的方法,另一个返回数字的方法:
public static int GetNumberOfDigits(this long value)
{
return value.GetDigits().Count();
}
public static IEnumerable<int> GetDigits(this long value)
{
do
{
yield return (int)(value % 10);
value /= 10;
} while (value != 0);
}
在解决此问题时,这感觉像是一种更直观的方法。由于其简单性,我首先尝试了Log10
方法,但是它遇到了很多极端情况和精度问题。
我还发现另一个答案中提出的if
链有点难看。
我知道这不是最有效的方法,但是它为您提供了另一个扩展名,也可以返回数字以用于其他用途(如果您不需要在外部使用它,则可以将其标记为private
该课程)。
请记住,它不会将负号视为数字。
答案 12 :(得分:0)
int i = 855865264;
int NumLen = i.ToString().Length;
答案 13 :(得分:-1)
这取决于你想要用digiths做什么。您可以通过这种方式从最后一个数字开始迭代到第一个数字:
int tmp=number;
int lastDigith = 0;
do
{
lastDigith = tmp/10;
doSomethingWithDigith(lastDigith);
tmp %= 10;
}while(tmp!=0);
答案 14 :(得分:-2)
转换为字符串然后你可以通过.length方法计算数字的数字。 像:
String numberString = "855865264".toString();
int NumLen = numberString .Length;
答案 15 :(得分:-3)
假设你的问题是指一个int,那么以下也适用于负/正和零:
Math.Floor((decimal) Math.Abs(n)).ToString().Length
答案 16 :(得分:-3)
如果它仅用于验证您可以执行:887979789 > 99999999