C#で数値の合計桁数を取得するにはどうすればよいですか?たとえば、887979789の数字は9桁です。
C#で数値の合計桁数を取得するにはどうすればよいですか?たとえば、887979789の数字は9桁です。
回答:
文字列に変換せずに、次のことを試すことができます。
Math.Ceiling(Math.Log10(n));
ysapのコメントに続く修正:
Math.Floor(Math.Log10(n) + 1);
n
が0
でき1
ます:)負の値を処理しすぎるn
と、単にに置き換えMath.Abs(n)
ます。
これを試して:
myint.ToString().Length
それは動作しますか ?
int
ので、それは問題ではないと思います。)
次の拡張メソッドのいずれかがこの仕事をします。それらのすべてはマイナス記号を数字と見なし、すべての可能な入力値に対して正しく機能します。また、.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;
}
この回答には、ランダムにサンプリングされた/ 数値の配列を使用して、Int32
およびの両方に対して実行されたテストが含まれます。ランダムデータセットは、テストを実行する前に前処理されて配列になります。Int64
100.000.000
int
long
4つの異なる方法のうちの整合性テストは、また、実行されたためMinValue
、負の境界場合、、 、-1
、0
、1
正の境界ケース、MaxValue
およびまた全体ランダムデータセットの。LOG10メソッドを除いて、上記で提供されたメソッドの整合性テストは失敗しません(これについては後で説明します)。
テストは.NET Framework 4.7.2
およびで実行されました.NET Core 2.2
。x86
およびx64
プラットフォーム用、64ビットインテルプロセッサーマシン、、Windows 10
およびVS2017 v.15.9.17
。次の4つのケースは、パフォーマンス結果に同じ影響を及ぼします。
.NET Framework(x86)
Platform = x86
Platform = AnyCPU
、Prefer 32-bit
プロジェクト設定でチェックされます
.NET Framework(x64)
Platform = x64
Platform = AnyCPU
、Prefer 32-bit
プロジェクト設定でオフになっている
.NET Core(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 Core(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方法はに鋳造で固定しなければならなかったdouble
内部Math.Abs()
入力値があるときの場合についてint.MinValue
、またはlong.MinValue
。
この質問を編集する前に私が実装した初期のパフォーマンステスト(すでに100万回編集する必要がありました)に関して、@GyörgyKőszegによって指摘された特定のケースがあり、IF-CHAINメソッドの実行がLOG10メソッドよりも低速でした。
@AlanSingfieldによって指摘された問題の修正後、差の大きさははるかに低くなりましたが、これはまだ起こります。この修正(キャストをに追加double
)すると、入力値が正確に-999999999999999999
次の場合に計算エラーが発生します。LOG10メソッドはの20
代わりに戻ります19
。LOG10メソッドには、if
には、入力値がゼロの場合のガードです。
LOG10メソッドは、すべての値に対して機能するように非常にトリッキーです。つまり、それを回避する必要があります。誰かが以下のすべての一貫性テストで正しく機能する方法を見つけたら、コメントを投稿してください!
WHILEメソッドは最近のリファクタリングバージョンも高速ですが、それでもまだ遅いです Platform = x86
(理由は今までわかりませんでした)。
STRINGメソッドは一貫して低速です。貪欲にメモリを割り当てすぎて何もしません。興味深いことに、.NET Coreでは、文字列の割り当ては.NET Frameworkよりもはるかに高速であるように見えます。知ってよかった。
IF-CHAINメソッドは、99.99%のケースで他のすべてのメソッドよりも優れているはずです。そして、私の個人的な意見では、あなたの最良の選択です(LOG10メソッドを正しく機能させるために必要なすべての調整と、他の2つのメソッドのパフォーマンスの低下を考慮してください)。
最後に、結果は次のとおりです。
これらの結果はハードウェアに依存するため、特定のケースで本当に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");
}
}
}
long.MaxValue
Log10の方がはるかに優れています。それとも.NET Coreだけですか?
Int32
てInt64
生成することに注意してください。これにより、一部のケースInt64
よりも速くなっInt32
た理由が説明される場合があります。ただし、Int32
テスト内およびテスト内ではInt64
、さまざまな計算方法をテストしてもデータセットは変更されません。.NET Coreに関しては、これらの結果を変えるような魔法の最適化がMathライブラリにあるとは思えませんが、それについてもっと聞きたいです(私の答えはすでに巨大で、おそらくSOで最大のものの1つです;-)
for
上のループをenumerations
、I前処理ランダムデータセット、およびジェネリック医薬品の使用を避ける、タスク、Function<>
、Action<>
、または任意のブラックボックス化測定フレームワーク)。要約すると、シンプルにしてください。また、すべての不要なアプリケーション(Skype、Windows Defender、アンチウイルス、Chrome、Microsoft Officeキャッシュなどを無効にする)を強制終了します。
直接C#ではありませんが、式は次のとおりです。 n = floor(log10(x)+1)
log10
ほとんどの場合、ライブラリ関数です。なぜ自分で実装したいのですか?また、どのような問題が発生しますか?log10(x) = log2(x) / log2(10)
、または一般的にlogA(x) = logB(x) / logB(A)
。
Log10(0)
-infinityだ。Math.Abs()
値をLog10に渡す前に使用しない限り、Log10 を使用して負の数字の桁数を計算することはできません。ただしMath.Abs(int.MinValue)
、例外がスローされます(long.MinValue
Int64の場合も同様)。Log10に渡す前に数値を2倍にキャストすると、-999999999999999999
(Int64の場合を除いて)ほとんどすべての数値で機能します。log10を使用し、int32またはint64値を入力として受け入れ、有効な値のみを出力する、桁数を計算するための式を知っていますか?
すでにここで回答は符号なし整数で機能しますが、10進数と2進数から桁数を取得するための適切な解決策は見つかりませんでした。
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
が、10進数にも制限があります。
スティーブの答えは正しいですが、1未満の整数では機能しません。
ここでは、ネガで機能する更新バージョン:
int digits = n == 0 ? 1 : Math.Floor(Math.Log10(Math.Abs(n)) + 1)
digits = n == 0 ? 1 : (int)Math.Floor(Math.Log10(Math.Abs(n)) + 1);
n = int.MinValue
。
再帰の使用(インタビューで時々尋ねられる)
public int CountDigits(int number)
{
// In case of negative numbers
number = Math.Abs(number);
if (number >= 10)
return CountDigits(number / 10) + 1;
return 1;
}
number = int.MinValue
。
static void Main(string[] args)
{
long blah = 20948230498204;
Console.WriteLine(blah.ToString().Length);
}
-1
= 2
これは、バイナリ検索を使用した実装です。これまでのところ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");
Int64
LookUpTableの実装はありますか?それとも、実装するには複雑すぎると思いますか?完全なセットで後でパフォーマンステストを実行したいと思います。
int i = 855865264;
int NumLen = i.ToString().Length;
string.TrimStart('-')
、より良い
すべての数字とそれを数える別の数字を返すメソッドを作成します。
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;
それはあなたが数字で何をしたいかによります。次のように、最後から最初の数字まで反復できます。
int tmp = number;
int lastDigit = 0;
do
{
lastDigit = tmp / 10;
doSomethingWithDigit(lastDigit);
tmp %= 10;
} while (tmp != 0);
%
して数字を取得し、それ/=
を削減する必要があります。
検証するためだけの場合: 887979789 > 99999999