簡體   English   中英

如何計算一個數字的總位數?

[英]How can I get a count of the total number of digits in a number?

如何計算 C# 中某個數字的總位數? 例如,數字 887979789 有 9 位數字。

無需轉換為字符串,您可以嘗試

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

試試這個:

myint.ToString().Length

那樣有用嗎 ?

解決方案

以下任何擴展方法都可以完成這項工作。 它們都將減號視為數字,並且對所有可能的輸入值都能正常工作。 它們也適用於 .NET Framework 和 .NET Core。 然而,存在相關的性能差異(如下所述),具體取決於您選擇的平台/框架。

Int32 版本:

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數字的數組。 在執行測試之前,隨機數據集被預處理成一個數組。

還執行了 4 種不同方法之間的一致性測試,對於MinValue 、負邊界情況、 -101 、正邊界情況、 MaxValue以及整個隨機數據集。 上面提供的方法沒有一致性測試失敗,除了 LOG10 方法(稍后討論)。

測試在.NET Framework 4.7.2.NET Core 2.2 對於x86x64平台,在 64 位英特爾處理器機器上,使用Windows 10VS2017 v.15.9.17 以下4種情況對性能結果有相同的影響:

.NET 框架 (x86)

  • Platform = x86

  • Platform = AnyCPU ,在項目設置中選中Prefer 32-bit

.NET 框架 (x64)

  • Platform = x64

  • Platform = AnyCPU ,在項目設置中取消選中Prefer 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注釋部分指出的那樣,LOG10方法必須固定有澆鑄到doubleMath.Abs()用於當輸入值是這樣int.MinValuelong.MinValue

關於我在編輯這個問題之前實施的早期性能測試(它已經被編輯了一百萬次), @GyörgyKőszeg指出了一個具體案例,其中 IF-CHAIN 方法的執行速度比 LOG10 方法慢。

這種情況仍然會發生,盡管在解決@AlanSingfield指出的問題后差異的幅度變得小得多 當輸入值正好是-999999999999999999時,此修復(向double添加強制轉換)會導致計算錯誤:LOG10 方法返回20而不是19 對於輸入值為零的情況,LOG10 方法還必須具有if保護。

LOG10 方法很難適用於所有值,這意味着您應該避免使用它。 如果有人找到一種方法使其在下面的所有一致性測試中都能正常工作,請發表評論!

WHILE 方法也有一個最近的重構版本,它更快,但對於Platform = x86仍然很慢(直到現在我找不到原因)。

STRING 方法一直很慢:它貪婪地分配了太多的內存。 有趣的是,在 .NET Core 中,字符串分配似乎比在 .NET Framework 中快得多。 很高興知道。

IF-CHAIN 方法應該在 99.99% 的情況下優於所有其他方法; 並且,在我個人看來,這是您的最佳選擇(考慮到使 LOG10 方法正確工作所需的所有調整,以及其他兩種方法的不良性能)。

最后,結果是:

在此處輸入圖片說明

由於這些結果取決於硬件,如果您確實需要在特定情況下 100% 確定,我建議無論如何在您自己的計算機上運行以下性能測試。

測試代碼

下面是性能測試和一致性測試的代碼。 .NET Framework 和 .NET Core 使用相同的代碼。

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");
        }
    }
}

不是直接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 ,但十進制也有限制。

史蒂夫的答案是正確的,但它不適用於小於 1 的整數。

這是一個適用於底片的更新版本:

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

使用遞歸(有時在面試中被問到)

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

    if (number >= 10)
        return CountDigits(number / 10) + 1;
    return 1;
 }
static void Main(string[] args)
{
    long blah = 20948230498204;
    Console.WriteLine(blah.ToString().Length);
}

將一個數字除以 10 會給你最左邊的數字,然后在數字上做一個 mod 10 給出沒有第一個數字的數字,然后重復這個直到你有所有的數字

這是使用二進制搜索的實現。 看起來是迄今為止最快的 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");
int i = 855865264;
int NumLen = i.ToString().Length;

整數的總位數:

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

無法發表評論,但這與 sɐunıɔןɐqɐp 的精彩評論有關。
這個 function 與雙打一起工作。 我也認為負面比較存在錯誤。

    /// <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 ) );
}

注意:最后一個返回零,我希望它為小於一但大於 -1 的值返回 0。

這取決於您究竟想對數字做什么。 您可以像這樣遍歷從最后一個到第一個的數字:

int tmp = number;
int lastDigit = 0;
do
{
    lastDigit = tmp / 10;
    doSomethingWithDigit(lastDigit);
    tmp %= 10;
} while (tmp != 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 -chain 有點難看。

我知道這不是最有效的方法,但它為您提供了另一個擴展來返回數字以及用於其他用途(如果您不需要在課堂外使用它,您可以將其標記為private )。

請記住,它不會將負號視為數字。

轉換為字符串,然后您可以通過 .length 方法計算數字的總數。 像:

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

如果它只是為了驗證你可以這樣做: 887979789 > 99999999

假設您的問題指的是 int,以下內容也適用於負/正和零:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM