我怎样才能得到一个数字的总数?

如何得到 C # 中一个数字的总数?例如,数字887979789有9个数字。

216071 次浏览

试试这个:

myint.ToString().Length

有用吗?

static void Main(string[] args)
{
long blah = 20948230498204;
Console.WriteLine(blah.ToString().Length);
}

把一个数字除以10会得到最左边的数字,然后对这个数字做10次修改就会得到一个没有第一个数字的数字,然后重复这个过程,直到你得到所有的数字

int i = 855865264;
int NumLen = i.ToString().Length;

这取决于你到底想用这些数字做什么。您可以循环遍历从最后一个到第一个的数字,如下所示:

int tmp = number;
int lastDigit = 0;
do
{
lastDigit = tmp / 10;
doSomethingWithDigit(lastDigit);
tmp %= 10;
} while (tmp != 0);

不需要转换为可以尝试的字符串

Math.Floor(Math.Log10(n) + 1);

不是直接的 C # ,但是公式是: n = floor(log10(x)+1)

这里的答案已经适用于无符号整数,但是我还没有找到从小数和双精度数中得到数位数的好的解决方案。

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,但小数也有限制。

如果它只是为了验证你可以做: 887979789 > 99999999

使用递归(有时在访谈中询问)

public int CountDigits(int number)
{
// In case of negative numbers
number = Math.Abs(number);


if (number >= 10)
return CountDigits(number / 10) + 1;
return 1;
}

史蒂夫说得对的答案,但它不适用于小于1的整数。

这里有一个更新的版本,可以用来处理底片:

int digits = n == 0 ? 1 : Math.Floor(Math.Log10(Math.Abs(n)) + 1)

转换成字符串,然后可以通过. length 方法计算总数。 比如:

String numberString = "855865264".toString();
int NumLen = numberString .Length;

假设你的问题指的是一个整型数,下面的方法同样适用于负/正数和零:

Math.Floor((decimal) Math.Abs(n)).ToString().Length

解决方案

下列任何一种扩展方法都可以完成这项工作。它们都将负号视为一个数字,并且正确地处理所有可能的输入值。他们也为。NET 架构及。NET 核心。然而,根据您对平台/框架的选择,存在相关的性能差异(将在下面讨论)。

版本:

public static class Int32Extensions
{
// IF-CHAIN:
public static int Digits_IfChain(this int n)
{
if (n >= 0)
{
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;
}
else
{
if (n > -10) return 2;
if (n > -100) return 3;
if (n > -1000) return 4;
if (n > -10000) return 5;
if (n > -100000) return 6;
if (n > -1000000) return 7;
if (n > -10000000) return 8;
if (n > -100000000) return 9;
if (n > -1000000000) return 10;
return 11;
}
}


// USING LOG10:
public static int Digits_Log10(this int n) =>
n == 0 ? 1 : (n > 0 ? 1 : 2) + (int)Math.Log10(Math.Abs((double)n));


// WHILE LOOP:
public static int Digits_While(this int n)
{
int digits = n < 0 ? 2 : 1;
while ((n /= 10) != 0) ++digits;
return digits;
}


// STRING CONVERSION:
public static int Digits_String(this int n) =>
n.ToString().Length;
}

Int64版本:

public static class Int64Extensions
{
// IF-CHAIN:
public static int Digits_IfChain(this long n)
{
if (n >= 0)
{
if (n < 10L) return 1;
if (n < 100L) return 2;
if (n < 1000L) return 3;
if (n < 10000L) return 4;
if (n < 100000L) return 5;
if (n < 1000000L) return 6;
if (n < 10000000L) return 7;
if (n < 100000000L) return 8;
if (n < 1000000000L) return 9;
if (n < 10000000000L) return 10;
if (n < 100000000000L) return 11;
if (n < 1000000000000L) return 12;
if (n < 10000000000000L) return 13;
if (n < 100000000000000L) return 14;
if (n < 1000000000000000L) return 15;
if (n < 10000000000000000L) return 16;
if (n < 100000000000000000L) return 17;
if (n < 1000000000000000000L) return 18;
return 19;
}
else
{
if (n > -10L) return 2;
if (n > -100L) return 3;
if (n > -1000L) return 4;
if (n > -10000L) return 5;
if (n > -100000L) return 6;
if (n > -1000000L) return 7;
if (n > -10000000L) return 8;
if (n > -100000000L) return 9;
if (n > -1000000000L) return 10;
if (n > -10000000000L) return 11;
if (n > -100000000000L) return 12;
if (n > -1000000000000L) return 13;
if (n > -10000000000000L) return 14;
if (n > -100000000000000L) return 15;
if (n > -1000000000000000L) return 16;
if (n > -10000000000000000L) return 17;
if (n > -100000000000000000L) return 18;
if (n > -1000000000000000000L) return 19;
return 20;
}
}


// USING LOG10:
public static int Digits_Log10(this long n) =>
n == 0L ? 1 : (n > 0L ? 1 : 2) + (int)Math.Log10(Math.Abs((double)n));


// WHILE LOOP:
public static int Digits_While(this long n)
{
int digits = n < 0 ? 2 : 1;
while ((n /= 10L) != 0L) ++digits;
return digits;
}


// STRING CONVERSION:
public static int Digits_String(this long n) =>
n.ToString().Length;
}

讨论

这个答案包括对 Int32Int64类型执行的测试,使用随机取样的 100.000.000数组 int/long数字。在执行测试之前,将随机数据集预处理为数组。

MinValue、阴性边界病例、 -101、阳性边界病例、 MaxValue以及整个随机数据集进行了一致性检验。上述提供的方法没有一致性测试失败,LOG10方法除外(稍后讨论)。

测试在 .NET Framework 4.7.2.NET Core 2.2上执行; 在 x86x64平台上执行,在64位 Intel 处理器机器上执行,使用 Windows 10VS2017 v.15.9.17。以下4种情况对业绩结果的影响相同:

.NET Framework (x86)

  • Platform = x86

  • 在项目设置中检查 Platform = AnyCPUPrefer 32-bit

.NET Framework (x64)

  • Platform = x64

  • Platform = AnyCPUPrefer 32-bit在项目设置中未选中

.NET 核心(x86)

  • "C:\Program Files (x86)\dotnet\dotnet.exe" bin\Release\netcoreapp2.2\ConsoleApp.dll

  • "C:\Program Files (x86)\dotnet\dotnet.exe" bin\x86\Release\netcoreapp2.2\ConsoleApp.dll

.NET 核心(x64)

  • "C:\Program Files\dotnet\dotnet.exe" bin\Release\netcoreapp2.2\ConsoleApp.dll

  • "C:\Program Files\dotnet\dotnet.exe" bin\x64\Release\netcoreapp2.2\ConsoleApp.dll

结果

下面的性能测试在整数可以假设的大范围值之间产生一个统一的值分布。这意味着用大量数字测试值的几率要高得多。在实际场景中,大多数值可能很小,因此 IF-CHAIN 的性能应该更好。此外,处理器将根据您的数据集缓存和优化 IF-CHAIN 决策。

正如 @ AlanSingfield在注释部分中指出的,当输入值为 int.MinValuelong.MinValue时,LOG10方法必须在 Math.Abs()内部对 double进行强制转换。

关于我在编辑这个问题之前实现的早期性能测试(它已经被编辑了一百万次) ,有一个由 @ Gy örgyK szeg指出的特殊情况,IF-CHAIN 方法执行的比 LOG10方法慢。

这种情况仍然会发生,尽管在 @ AlanSingfield指出的问题得到解决之后,差异的幅度变得小得多。当输入值正好是 -999999999999999999时,这个修复(向 double添加强制转换)会导致计算错误: LOG10方法返回 20而不是 19。LOG10方法还必须为输入值为零的情况提供 if保护。

LOG10方法很难为所有值工作,这意味着您应该避免使用它。如果有人发现一种方法,使其正确工作的所有一致性测试下面,请发表评论!

WHILE 方法也得到了一个最近重构的版本,这个版本更快,但是对于 Platform = x86来说仍然很慢(直到现在我才找到原因)。

STRING 方法一直都很慢: 它贪婪地分配太多的内存而什么都不做。有趣的是。NET 核心,字符串分配似乎比在。NET 架构。很高兴知道。

在99.99% 的情况下,IF-CHAIN 方法的性能应该优于其他所有方法; 而且,在我个人看来,它是您的最佳选择(考虑到所有必要的调整以使 LOG10方法正常工作,以及其他两种方法的糟糕性能)。

最后,结果是:

enter image description here

由于这些结果是依赖于硬件的,因此如果您确实需要在特定情况下100% 确定,我建议您在自己的计算机上运行以下性能测试。

测试代码

下面是性能测试和一致性测试的代码。两者使用相同的代码。NET 架构及。NET 核心。

using System;
using System.Diagnostics;


namespace NumberOfDigits
{
// Performance Tests:
class Program
{
private static void Main(string[] args)
{
Console.WriteLine("\r\n.NET Core");


RunTests_Int32();
RunTests_Int64();
}


// Int32 Performance Tests:
private static void RunTests_Int32()
{
Console.WriteLine("\r\nInt32");


const int size = 100000000;
int[] samples = new int[size];
Random random = new Random((int)DateTime.Now.Ticks);
for (int i = 0; i < size; ++i)
samples[i] = random.Next(int.MinValue, int.MaxValue);


Stopwatch sw1 = new Stopwatch();
sw1.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_IfChain();
sw1.Stop();
Console.WriteLine($"IfChain: {sw1.ElapsedMilliseconds} ms");


Stopwatch sw2 = new Stopwatch();
sw2.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_Log10();
sw2.Stop();
Console.WriteLine($"Log10: {sw2.ElapsedMilliseconds} ms");


Stopwatch sw3 = new Stopwatch();
sw3.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_While();
sw3.Stop();
Console.WriteLine($"While: {sw3.ElapsedMilliseconds} ms");


Stopwatch sw4 = new Stopwatch();
sw4.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_String();
sw4.Stop();
Console.WriteLine($"String: {sw4.ElapsedMilliseconds} ms");




// Start of consistency tests:
Console.WriteLine("Running consistency tests...");
bool isConsistent = true;


// Consistency test on random set:
for (int i = 0; i < samples.Length; ++i)
{
int s = samples[i];
int a = s.Digits_IfChain();
int b = s.Digits_Log10();
int c = s.Digits_While();
int d = s.Digits_String();
if (a != b || c != d || a != c)
{
Console.WriteLine($"Digits({s}): IfChain={a} Log10={b} While={c} String={d}");
isConsistent = false;
break;
}
}


// Consistency test of special values:
samples = new int[]
{
0,
int.MinValue, -1000000000, -999999999, -100000000, -99999999, -10000000, -9999999, -1000000, -999999, -100000, -99999, -10000, -9999, -1000, -999, -100, -99, -10, -9, - 1,
int.MaxValue, 1000000000, 999999999, 100000000, 99999999, 10000000, 9999999, 1000000, 999999, 100000, 99999, 10000, 9999, 1000, 999, 100, 99, 10, 9,  1,
};
for (int i = 0; i < samples.Length; ++i)
{
int s = samples[i];
int a = s.Digits_IfChain();
int b = s.Digits_Log10();
int c = s.Digits_While();
int d = s.Digits_String();
if (a != b || c != d || a != c)
{
Console.WriteLine($"Digits({s}): IfChain={a} Log10={b} While={c} String={d}");
isConsistent = false;
break;
}
}


// Consistency test result:
if (isConsistent)
Console.WriteLine("Consistency tests are OK");
}


// Int64 Performance Tests:
private static void RunTests_Int64()
{
Console.WriteLine("\r\nInt64");


const int size = 100000000;
long[] samples = new long[size];
Random random = new Random((int)DateTime.Now.Ticks);
for (int i = 0; i < size; ++i)
samples[i] = Math.Sign(random.Next(-1, 1)) * (long)(random.NextDouble() * long.MaxValue);


Stopwatch sw1 = new Stopwatch();
sw1.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_IfChain();
sw1.Stop();
Console.WriteLine($"IfChain: {sw1.ElapsedMilliseconds} ms");


Stopwatch sw2 = new Stopwatch();
sw2.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_Log10();
sw2.Stop();
Console.WriteLine($"Log10: {sw2.ElapsedMilliseconds} ms");


Stopwatch sw3 = new Stopwatch();
sw3.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_While();
sw3.Stop();
Console.WriteLine($"While: {sw3.ElapsedMilliseconds} ms");


Stopwatch sw4 = new Stopwatch();
sw4.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_String();
sw4.Stop();
Console.WriteLine($"String: {sw4.ElapsedMilliseconds} ms");


// Start of consistency tests:
Console.WriteLine("Running consistency tests...");
bool isConsistent = true;


// Consistency test on random set:
for (int i = 0; i < samples.Length; ++i)
{
long s = samples[i];
int a = s.Digits_IfChain();
int b = s.Digits_Log10();
int c = s.Digits_While();
int d = s.Digits_String();
if (a != b || c != d || a != c)
{
Console.WriteLine($"Digits({s}): IfChain={a} Log10={b} While={c} String={d}");
isConsistent = false;
break;
}
}


// Consistency test of special values:
samples = new long[]
{
0,
long.MinValue, -1000000000000000000, -999999999999999999, -100000000000000000, -99999999999999999, -10000000000000000, -9999999999999999, -1000000000000000, -999999999999999, -100000000000000, -99999999999999, -10000000000000, -9999999999999, -1000000000000, -999999999999, -100000000000, -99999999999, -10000000000, -9999999999, -1000000000, -999999999, -100000000, -99999999, -10000000, -9999999, -1000000, -999999, -100000, -99999, -10000, -9999, -1000, -999, -100, -99, -10, -9, - 1,
long.MaxValue, 1000000000000000000, 999999999999999999, 100000000000000000, 99999999999999999, 10000000000000000, 9999999999999999, 1000000000000000, 999999999999999, 100000000000000, 99999999999999, 10000000000000, 9999999999999, 1000000000000, 999999999999, 100000000000, 99999999999, 10000000000, 9999999999, 1000000000, 999999999, 100000000, 99999999, 10000000, 9999999, 1000000, 999999, 100000, 99999, 10000, 9999, 1000, 999, 100, 99, 10, 9,  1,
};
for (int i = 0; i < samples.Length; ++i)
{
long s = samples[i];
int a = s.Digits_IfChain();
int b = s.Digits_Log10();
int c = s.Digits_While();
int d = s.Digits_String();
if (a != b || c != d || a != c)
{
Console.WriteLine($"Digits({s}): IfChain={a} Log10={b} While={c} String={d}");
isConsistent = false;
break;
}
}


// Consistency test result:
if (isConsistent)
Console.WriteLine("Consistency tests are OK");
}
}
}

这是一个使用二进制搜索的实现,看起来是 int32目前为止最快的。

Int64实现留给读者作为练习(!)

我尝试使用 Array.BinarySearch 而不是硬编码树,但这只是速度的一半。

编辑: 查找表比二进制搜索快得多,代价是使用更多的内存。实际上,我可能会在生产中使用二进制搜索,查找表是一个非常复杂的速度增益,可能会掩盖了软件的其他部分。

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];
}

二进制搜索版本

        public static int Digits_BinarySearch(this int n)
{
if(n >= 0)
{
if(n <= 9999) // 0 .. 9999
{
if(n <= 99) // 0 .. 99
{
return (n <= 9) ? 1 : 2;
}
else // 100 .. 9999
{
return (n <= 999) ? 3 : 4;
}
}
else // 10000 .. int.MaxValue
{
if(n <= 9_999_999) // 10000 .. 9,999,999
{
if(n <= 99_999)
return 5;
else if(n <= 999_999)
return 6;
else
return 7;
}
else // 10,000,000 .. int.MaxValue
{
if(n <= 99_999_999)
return 8;
else if(n <= 999_999_999)
return 9;
else
return 10;
}
}
}
else
{
if(n >= -9999) // -9999 .. -1
{
if(n >= -99) // -99 .. -1
{
return (n >= -9) ? 1 : 2;
}
else // -9999 .. -100
{
return (n >= -999) ? 3 : 4;
}
}
else // int.MinValue .. -10000
{
if(n >= -9_999_999) // -9,999,999 .. -10000
{
if(n >= -99_999)
return 5;
else if(n >= -999_999)
return 6;
else
return 7;
}
else // int.MinValue .. -10,000,000
{
if(n >= -99_999_999)
return 8;
else if(n >= -999_999_999)
return 9;
else
return 10;
}
}
}
}


Stopwatch sw0 = new Stopwatch();
sw0.Start();
for(int i = 0; i < size; ++i) samples[i].Digits_BinarySearch();
sw0.Stop();
Console.WriteLine($"Binary-Search: {sw0.ElapsedMilliseconds} ms");

创建一个返回所有数字的方法,另一个返回计数数字的方法:

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)。

请记住,它不认为负号是一个数字。

整数总数:

      double input = Convert.ToDouble(Console.ReadLine());
double b = Math.Floor(Math.Log10(input) + 1);
int c = Convert.ToInt32(b);

无法评论,但这与 s un q p 的优秀评论有关。
此函数适用于双精度浮点数。 我也相信负面比较是错误的。

    /// <summary>
/// counts the digits of the integral part of a number. <br></br>
///  4 -> 1; 4.3 -> 1; -4 -> 1; -0.4 -> 0, 1e53 -> 53
/// </summary>
/// <param name="n"></param>
/// <returns>number 1+</returns>
public static int IntegralDigitLength( double n )
{
//this if-chain is allegedly the best way
//https://stackoverflow.com/questions/4483886/how-can-i-get-a-count-of-the-total-number-of-digits-in-a-number
if(n< 1 && n > -1 )
{
return 0;
}
if( n >= 0 )
{
if( n < 10L ) return 1;
if( n < 100L ) return 2;
if( n < 1000L ) return 3;
if( n < 10000L ) return 4;
if( n < 100000L ) return 5;
if( n < 1000000L ) return 6;
if( n < 10000000L ) return 7;
if( n < 100000000L ) return 8;
if( n < 1000000000L ) return 9;
if( n < 10000000000L ) return 10;
if( n < 100000000000L ) return 11;
if( n < 1000000000000L ) return 12;
if( n < 10000000000000L ) return 13;
if( n < 100000000000000L ) return 14;
if( n < 1000000000000000L ) return 15;
if( n < 10000000000000000L ) return 16;
if( n < 100000000000000000L ) return 17;
if( n < 1000000000000000000L ) return 18;


n = Math.Floor( n );
var numOfDigits = 19;
while( true )
{


double comparison = Math.Pow( 10, numOfDigits );
if( n <= comparison )
{
return numOfDigits;
}
numOfDigits++;
}
}
else
{
if( n > -10L ) return 1;
if( n > -100L ) return 2;
if( n > -1000L ) return 3;
if( n > -10000L ) return 4;
if( n > -100000L ) return 5;
if( n > -1000000L ) return 6;
if( n > -10000000L ) return 7;
if( n > -100000000L ) return 8;
if( n > -1000000000L ) return 9;
if( n > -10000000000L ) return 10;
if( n > -100000000000L ) return 11;
if( n > -1000000000000L ) return 12;
if( n > -10000000000000L ) return 13;
if( n > -100000000000000L ) return 14;
if( n > -1000000000000000L ) return 15;
if( n > -10000000000000000L ) return 16;
if( n > -100000000000000000L ) return 17;
if( n > -1000000000000000000L ) return 18;
n = Math.Floor( n );
var numOfDigits = 19;
while( true )
{
if( n <= Math.Pow( -10, numOfDigits ) )
{
return numOfDigits;
}
numOfDigits++;
}
}
}

它通过了以下单元测试:

    [Test]
public void IntegralDigitLength()
{


Assert.AreEqual( 1, Logic.IntegralDigitLength( 1 ) );
Assert.AreEqual( 1, Logic.IntegralDigitLength( 2 ) );
Assert.AreEqual( 1, Logic.IntegralDigitLength( -3 ) );
Assert.AreEqual( 1, Logic.IntegralDigitLength( -3.4 ) );
Assert.AreEqual( 1, Logic.IntegralDigitLength( 3.4 ) );
Assert.AreEqual( 1, Logic.IntegralDigitLength( 9.9 ) );
Assert.AreEqual( 2, Logic.IntegralDigitLength( 10 ) );
Assert.AreEqual( 2, Logic.IntegralDigitLength( 19 ) );
Assert.AreEqual( 2, Logic.IntegralDigitLength( 19.9 ) );
Assert.AreEqual( 2, Logic.IntegralDigitLength( -19.9 ) );
Assert.AreEqual( 5, Logic.IntegralDigitLength( 12345 ) );
Assert.AreEqual( 5, Logic.IntegralDigitLength( 92345 ) );
Assert.AreEqual( 4, Logic.IntegralDigitLength( 02345 ) );
Assert.AreEqual( 1, Logic.IntegralDigitLength( 00005 ) );
Assert.AreEqual( 8, Logic.IntegralDigitLength( 47616294 ) );
Assert.AreEqual( 8, Logic.IntegralDigitLength( -47616294 ) );
Assert.AreEqual( 25, Logic.IntegralDigitLength( 1111111111111111111111111f ) );
Assert.AreEqual( 25, Logic.IntegralDigitLength( 4444444444444444444444444f ) );
Assert.AreEqual( 25, Logic.IntegralDigitLength( 9999999999999999999999999f ) );
Assert.AreEqual( 25, Logic.IntegralDigitLength( 1e25 ) );
Assert.AreEqual( 305, Logic.IntegralDigitLength( 1e305 ) );
Assert.AreEqual( 0, Logic.IntegralDigitLength( 1e-3 ) );
}

注意: 最后一个返回0,如果值小于1但大于 -1,我希望它返回0。