C #에서 숫자의 총 자릿수를 어떻게 구할 수 있습니까? 예를 들어, 숫자 887979789는 9 자리 숫자입니다.
C #에서 숫자의 총 자릿수를 어떻게 구할 수 있습니까? 예를 들어, 숫자 887979789는 9 자리 숫자입니다.
답변:
문자열로 변환하지 않고 시도해 볼 수 있습니다.
Math.Ceiling(Math.Log10(n));
ysap의 의견에 따른 수정 :
Math.Floor(Math.Log10(n) + 1);
n
IS는 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
.
이 질문을 편집하기 전에 구현 한 초기 성능 테스트와 관련하여 (이미 백만 번 편집해야 함) @ GyörgyKőszeg가 지적한 특정 사례 가 있는데, IF-CHAIN 방법이 LOG10 방법보다 느리게 수행됩니다.
@AlanSingfield가 지적한 문제에 대한 수정 이후 차이의 크기가 훨씬 낮아졌지만 여전히 발생합니다 . 이 수정 (캐스트 추가 double
)은 입력 값이 정확히 -999999999999999999
다음과 같을 때 계산 오류를 발생시킵니다 . 20
대신 LOG10 메서드가 반환 됩니다 19
. LOG10 메서드 if
에는 입력 값이 0 인 경우에 대한 가드 도 있어야합니다 .
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");
}
}
}
long.MaxValue
Log10의 경우 훨씬 더 좋습니다. 아니면 .NET Core에 있습니까?
Int32
하고 Int64
생성 Int64
하므로 Int32
어떤 경우 보다 빨라진 이유를 설명 할 수 있습니다 . 내 비록 Int32
테스트 및 내 Int64
다른 계산 방법을 테스트 할 때의 데이터 세트가 변경되지 않은 시험. 지금은 어떤 마법 최적화이 결과를 바꿀 것 수학 라이브러리가 의심, .NET 핵심에 대한,하지만 내 대답은 아마 이미 ;-) SO에서 가장 큰 중 하나 크다 (더 그것에 대해 듣고 싶어요
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)
것이 아니라 무한대입니다. Log10 Math.Abs()
에 값을 전달하기 전에 사용하지 않으면 Log10 을 사용하여 음수의 자릿수를 계산할 수 없습니다 . 그러나 Math.Abs(int.MinValue)
예외가 발생합니다 ( long.MinValue
Int64의 경우에도). Log10에 전달하기 전에 숫자를 double로 캐스트하면 -999999999999999999
(Int64의 경우)를 제외한 거의 모든 숫자에 대해 작동합니다 . log10을 사용하고 int32 또는 int64 값을 입력으로 받아들이고 유효한 값만 출력하는 자릿수를 계산하는 공식을 알고 있습니까?
이미 여기에있는 답변은 부호없는 정수에 대해 작동하지만 소수와 두 배에서 자릿수를 얻는 좋은 솔루션을 찾지 못했습니다.
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
있지만 십진수도 제한이 있습니다.
Steve 의 대답 은 맞지만 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
합니다.
다음은 이진 검색을 사용한 구현입니다. 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에 대한 구현이 있습니까? 아니면 구현하기가 너무 복잡하다고 생각하십니까? 나중에 전체 세트에서 성능 테스트를 실행하고 싶습니다.
모든 숫자를 반환하는 메서드와 숫자를 계산하는 다른 메서드를 만듭니다.
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
귀하의 질문이 int를 참조한다고 가정하면 다음은 음수 / 양수 및 0에서도 작동합니다.
Math.Floor((decimal) Math.Abs(n)).ToString().Length