在 C# 中,获取一个整数的第一位数字的最佳方法是什么?我想到了将整数转为字符串,找到字符串的第一个字符,然后再将其转回整数。
int start = Convert.ToInt32(curr.ToString().Substring(0, 1));
虽然这种方式能够解决问题,但感觉可能有一种好的、简单的基于数学的解决方案。字符串操作感觉不太优雅。
编辑:无论速度差异如何,使用mystring[0]而不是Substring()仍然只是一种字符串操作。
在 C# 中,获取一个整数的第一位数字的最佳方法是什么?我想到了将整数转为字符串,找到字符串的第一个字符,然后再将其转回整数。
int start = Convert.ToInt32(curr.ToString().Substring(0, 1));
虽然这种方式能够解决问题,但感觉可能有一种好的、简单的基于数学的解决方案。字符串操作感觉不太优雅。
编辑:无论速度差异如何,使用mystring[0]而不是Substring()仍然只是一种字符串操作。
首先,您必须确定您所说的“最佳”解决方案是什么意思,当然,这考虑到算法的效率、可读性/可维护性以及将来出现错误的可能性。不过,仔细的单元测试通常可以避免这些问题。
我对每个示例运行了1000万次,并且结果值是经过的ElapsedTicks
数量。
接下来,按照速度从慢到快,这些算法如下:
int firstDigit = (int)(Value.ToString()[0]) - 48;
结果:
12,552,893 ticks
int firstDigit = (int)(Value / Math.Pow(10, (int)Math.Floor(Math.Log10(Value))));
结果:
9,165,089 ticks
while (number >= 10)
number /= 10;
结果:
6,001,570 ticks
int firstdigit;
if (Value < 10)
firstdigit = Value;
else if (Value < 100)
firstdigit = Value / 10;
else if (Value < 1000)
firstdigit = Value / 100;
else if (Value < 10000)
firstdigit = Value / 1000;
else if (Value < 100000)
firstdigit = Value / 10000;
else if (Value < 1000000)
firstdigit = Value / 100000;
else if (Value < 10000000)
firstdigit = Value / 1000000;
else if (Value < 100000000)
firstdigit = Value / 10000000;
else if (Value < 1000000000)
firstdigit = Value / 100000000;
else
firstdigit = Value / 1000000000;
结果:
1,421,659 ticks
if (i >= 100000000) i /= 100000000;
if (i >= 10000) i /= 10000;
if (i >= 100) i /= 100;
if (i >= 10) i /= 10;
结果:
1,399,788 ticks
注意:
每个测试调用Random.Next()
以获取下一个int
。
char
强制转换为 int
会计算出字符的代码点,因此将字符 0
转换后的值为 48。减去 48 实际上是将其转换为整数。另一个例子,将字符 5
转换为 int
的值为 53,从中减去 48 的结果为 5。 - John Rasch以下是方法
int i = Math.Abs(386792);
while(i >= 10)
i /= 10;
而 i
将包含您需要的内容
试试这个
public int GetFirstDigit(int number) {
if ( number < 10 ) {
return number;
}
return GetFirstDigit ( (number - (number % 10)) / 10);
}
编辑
有几个人要求循环版本。
public static int GetFirstDigitLoop(int number)
{
while (number >= 10)
{
number = (number - (number % 10)) / 10;
}
return number;
}
我最能想到的是:
int numberOfDigits = Convert.ToInt32(Math.Floor( Math.Log10( value ) ) );
int firstDigit = value / Math.Pow( 10, numberOfDigits );
Anton的答案变体:
// cut down the number of divisions (assuming i is positive & 32 bits)
if (i >= 100000000) i /= 100000000;
if (i >= 10000) i /= 10000;
if (i >= 100) i /= 100;
if (i >= 10) i /= 10;
/10
和 /1000
。你仍然可以更积极地进行除法,但是会少一些混乱。对创意加一分 :) - Samantha Branhamint myNumber = 8383;
char firstDigit = myNumber.ToString()[0];
// char = '8'
int start = number == 0 ? 0 : number / (int) Math.Pow(10,Math.Floor(Math.Log10(Math.Abs(number))));
... leading code along the same lines
/* i<10000 */
if (i >= 100){
if (i >= 1000){
return i/1000;
}
else /* i<1000 */{
return i/100;
}
}
else /* i<100*/ {
if (i >= 10){
return i/10;
}
else /* i<10 */{
return i;
}
}
顺便说一句,MartinStettner也有同样的想法。
i=(...moreugly...)i>=100?i>=1000?i/1000:i/100:i>=10?i/10:i;
怎么样? - David Murdoch我刚刚偶然发现了这个旧问题,并倾向于提出另一个建议,因为迄今为止没有一个答案能够返回所有可能输入值的正确结果,而且它仍然可以更快地实现:
public static int GetFirstDigit( int i )
{
if( i < 0 && ( i = -i ) < 0 ) return 2;
return ( i < 100 ) ? ( i < 1 ) ? 0 : ( i < 10 )
? i : i / 10 : ( i < 1000000 ) ? ( i < 10000 )
? ( i < 1000 ) ? i / 100 : i / 1000 : ( i < 100000 )
? i / 10000 : i / 100000 : ( i < 100000000 )
? ( i < 10000000 ) ? i / 1000000 : i / 10000000
: ( i < 1000000000 ) ? i / 100000000 : i / 1000000000;
}
-2147483648
,它没有正数对应。 Math.Abs(-2147483648)
会触发System.OverflowException
,而--2147483648
计算结果为-2147483648
。public static int GetFirstDigitX( int i )
{
if( i < 0 && ( i = -i ) < 0 ) return 2;
if( i >= 100000000 ) i /= 100000000;
if( i >= 10000 ) i /= 10000;
if( i >= 100 ) i /= 100;
if( i >= 10 ) i /= 10;
return i;
}
在我的电脑上,对于这个测试,需要16,561,929个时钟周期才能得到同样的修正结果。
public static int GetFirstDigitY( int i )
{
if( i < 0 && ( i = -i ) < 0 ) return 2;
while( i >= 10 )
i /= 10;
return i;
}
像这样简单的函数可以很容易地被证明为正确,因为在当前硬件上迭代所有可能的整数值不需要花费太多时间,只需几秒钟即可。这意味着重要的是以非常易读的方式实现它们,因为以后根本没有必要修复其中的错误。
if(i<10)
firstdigit = i;
else if (i<100)
firstdigit = i/10;
else if (i<1000)
firstdigit = i/100;
else if (i<10000)
firstdigit = i/1000;
else if (i<100000)
firstdigit = i/10000;
else (etc... all the way up to 1000000000)