有没有比这个方法更简洁的获取一个整数位数的方式?
int numDigits = String.valueOf(1000).length();
有没有比这个方法更简洁的获取一个整数位数的方式?
int numDigits = String.valueOf(1000).length();
那就来点老套的数学吧!将数字除以10,直到结果为0。
public static int getSize(long number) {
int count = 0;
while (number > 0) {
count += 1;
number = (number / 10);
}
return count;
}
Long.MAX_VALUE
,这是你的代码的最坏复杂度情况,并使用 System.nanoTime()
对其他解决方案的最坏复杂度情况进行计时试验。++实际上,也尝试使用随机化器填充的数组,范围设置为 0
到 Long.MAX_VALUE
,以进行“平均复杂度”测试++ 你可能会发现结果...非常令人震惊。 - CosmicGiantint
,这个循环最多执行11次。你有什么证据支持你的说法吗? - user207421我可以试试吗? ;)
基于Dirk的解决方案
final int digits = number==0?1:(1 + (int)Math.floor(Math.log10(Math.abs(number))));
Math.abs()
无法处理 Integer.MIN_VALUE
。 - nmatt现在的Marian解决方案采用三进制:
public int len(int n){
return (n<100000)?((n<100)?((n<10)?1:2):(n<1000)?3:((n<10000)?4:5)):((n<10000000)?((n<1000000)?6:7):((n<100000000)?8:((n<1000000000)?9:10)));
}
public static int getNumberOfDigits(int input) {
int numOfDigits = 1;
int base = 1;
while (input >= base * 10) {
base = base * 10;
numOfDigits++;
}
return numOfDigits;
}
for (int x = 1, i = 0; i < 32; ++i) { System.out.println(x *= 10); }
- nmatt好奇心驱使我尝试对其进行基准测试...
import org.junit.Test;
import static org.junit.Assert.*;
public class TestStack1306727 {
@Test
public void bench(){
int number=1000;
int a= String.valueOf(number).length();
int b= 1 + (int)Math.floor(Math.log10(number));
assertEquals(a,b);
int i=0;
int s=0;
long startTime = System.currentTimeMillis();
for(i=0, s=0; i< 100000000; i++){
a= String.valueOf(number).length();
s+=a;
}
long stopTime = System.currentTimeMillis();
long runTime = stopTime - startTime;
System.out.println("Run time 1: " + runTime);
System.out.println("s: "+s);
startTime = System.currentTimeMillis();
for(i=0,s=0; i< 100000000; i++){
b= number==0?1:(1 + (int)Math.floor(Math.log10(Math.abs(number))));
s+=b;
}
stopTime = System.currentTimeMillis();
runTime = stopTime - startTime;
System.out.println("Run time 2: " + runTime);
System.out.println("s: "+s);
assertEquals(a,b);
}
}
结果如下:
运行时间 1: 6765 s: 400000000 运行时间 2: 6000 s: 400000000
现在我不禁要想我的基准测试是否有意义,但我确实在多次运行基准测试时得到了一致的结果(在毫秒级别内存在变化)... :) 看起来优化这个测试是无用的...
编辑:根据ptomli的评论,我在上面的代码中将“number”替换为“i”,并在5次测试中得到以下结果:
运行时间1:11500 s:788888890 运行时间2:8547 s:788888890
运行时间1:11485 s:788888890 运行时间2:8547 s:788888890
运行时间1:11469 s:788888890 运行时间2:8547 s:788888890
运行时间1:11500 s:788888890 运行时间2:8547 s:788888890
运行时间1:11484 s:788888890 运行时间2:8547 s:788888890
使用设计(基于问题)。这是分治算法的替代方法。我们将首先定义一个枚举类型(考虑它仅用于无符号整数)。
public enum IntegerLength {
One((byte)1,10),
Two((byte)2,100),
Three((byte)3,1000),
Four((byte)4,10000),
Five((byte)5,100000),
Six((byte)6,1000000),
Seven((byte)7,10000000),
Eight((byte)8,100000000),
Nine((byte)9,1000000000);
byte length;
int value;
IntegerLength(byte len,int value) {
this.length = len;
this.value = value;
}
public byte getLenght() {
return length;
}
public int getValue() {
return value;
}
}
public class IntegerLenght {
public static byte calculateIntLenght(int num) {
for(IntegerLength v : IntegerLength.values()) {
if(num < v.getValue()){
return v.getLenght();
}
}
return 0;
}
}
或者,您可以检查数字是否大于或小于所需数字,而不是长度。
public void createCard(int cardNumber, int cardStatus, int customerId) throws SQLException {
if(cardDao.checkIfCardExists(cardNumber) == false) {
if(cardDao.createCard(cardNumber, cardStatus, customerId) == true) {
System.out.println("Card created successfully");
} else {
}
} else {
System.out.println("Card already exists, try with another Card Number");
do {
System.out.println("Enter your new Card Number: ");
scan = new Scanner(System.in);
int inputCardNumber = scan.nextInt();
cardNumber = inputCardNumber;
} while(cardNumber < 95000000);
cardDao.createCard(cardNumber, cardStatus, customerId);
}
}
}
我还没有看到基于乘法的解决方案。对于数百万个测试用例,对数、除法和基于字符串的解决方案将变得相当笨重,因此这里有一个针对 ints
的解决方案:
/**
* Returns the number of digits needed to represents an {@code int} value in
* the given radix, disregarding any sign.
*/
public static int len(int n, int radix) {
radixCheck(radix);
// if you want to establish some limitation other than radix > 2
n = Math.abs(n);
int len = 1;
long min = radix - 1;
while (n > min) {
n -= min;
min *= radix;
len++;
}
return len;
}
在十进制中,这是有效的,因为n本质上被比较为9、99、999...,而min则为9、90、900...,并且n被减去9、90、900...
不幸的是,由于溢出,仅仅替换每个int
实例就无法将其移植到long
。另一方面,碰巧它对于2和10进制是有效的(但对于大多数其他进制则失败得很惨)。您需要一个查找表来查找溢出点(或者进行除法测试...呕)。
/**
* For radices 2 &le r &le Character.MAX_VALUE (36)
*/
private static long[] overflowpt = {-1, -1, 4611686018427387904L,
8105110306037952534L, 3458764513820540928L, 5960464477539062500L,
3948651115268014080L, 3351275184499704042L, 8070450532247928832L,
1200757082375992968L, 9000000000000000000L, 5054470284992937710L,
2033726847845400576L, 7984999310198158092L, 2022385242251558912L,
6130514465332031250L, 1080863910568919040L, 2694045224950414864L,
6371827248895377408L, 756953702320627062L, 1556480000000000000L,
3089447554782389220L, 5939011215544737792L, 482121737504447062L,
839967991029301248L, 1430511474609375000L, 2385723916542054400L,
3902460517721977146L, 6269893157408735232L, 341614273439763212L,
513726300000000000L, 762254306892144930L, 1116892707587883008L,
1617347408439258144L, 2316231840055068672L, 3282671350683593750L,
4606759634479349760L};
public static int len(long n, int radix) {
radixCheck(radix);
n = abs(n);
int len = 1;
long min = radix - 1;
while (n > min) {
len++;
if (min == overflowpt[radix]) break;
n -= min;
min *= radix;
}
return len;
}
public static int digitCount(int numberInput, int i) {
while (numberInput > 0) {
i++;
numberInput = numberInput / 10;
digitCount(numberInput, i);
}
return i;
}
public static void printString() {
int numberInput = 1234567;
int digitCount = digitCount(numberInput, 0);
System.out.println("Count of digit in ["+numberInput+"] is ["+digitCount+"]");
}
这取决于你对“整洁”的理解。我认为以下代码非常整洁,而且运行速度快。
它基于Marian的答案,扩展到适用于所有long
值,并使用? :
操作符进行渲染。
private static long[] DIGITS = { 1l,
10l,
100l,
1000l,
10000l,
100000l,
1000000l,
10000000l,
100000000l,
1000000000l,
10000000000l,
100000000000l,
1000000000000l,
10000000000000l,
100000000000000l,
1000000000000000l,
10000000000000000l,
100000000000000000l,
1000000000000000000l };
public static int numberOfDigits(final long n)
{
return n == Long.MIN_VALUE ? 19 : n < 0l ? numberOfDigits(-n) :
n < DIGITS[8] ? // 1-8
n < DIGITS[4] ? // 1-4
n < DIGITS[2] ? // 1-2
n < DIGITS[1] ? 1 : 2 : // 1-2
n < DIGITS[3] ? 3 : 4 : // 3-4
n < DIGITS[6] ? // 5-8
n < DIGITS[5] ? 5 : 6 : // 5-6
n < DIGITS[7] ? 7 : 8 : // 7-8
n < DIGITS[16] ? // 9-16
n < DIGITS[12] ? // 9-12
n < DIGITS[10] ? // 9-10
n < DIGITS[9] ? 9 : 10 : // 9-10
n < DIGITS[11] ? 11 : 12 : // 11-12
n < DIGITS[14] ? // 13-16
n < DIGITS[13] ? 13 : 14 : // 13-14
n < DIGITS[15] ? 15 : 16 : // 15-16
n < DIGITS[17] ? 17 : // 17-19
n < DIGITS[18] ? 18 :
19;
}