有没有比这个方法更简洁的方法来获取整数的位数?

int numDigits = String.valueOf(1000).length();

当前回答

我还没有看到基于乘法的解决方案。对数、除法和基于字符串的解决方案将在数百万个测试用例中变得相当笨拙,所以这里有一个int型的解决方案:

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

以10为基底,这是可行的,因为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;
}

其他回答

你的基于字符串的解决方案是完全OK的,没有什么“不整洁”的。你必须意识到,在数学上,数字没有长度,也没有数字。长度和数字都是数字在特定基底(即字符串)中的物理表示形式的属性。

基于对数的解决方案在内部完成(部分)与基于字符串的解决方案相同的工作,并且可能(微不足道地)更快,因为它只生成长度而忽略数字。但实际上我并不认为它的意图更明确——这是最重要的因素。

由于以10为基数的整数的位数只是1 + truncate(log10(number)),您可以这样做:

public class Test {

    public static void main(String[] args) {

        final int number = 1234;
        final int digits = 1 + (int)Math.floor(Math.log10(number));

        System.out.println(digits);
    }
}

被编辑是因为我的最后一次编辑修复了代码示例,但没有修复描述。

一个非常简单的解决方案:

public int numLength(int n) {
  for (int length = 1; n % Math.pow(10, length) != n; length++) {}
  return length;
}

用设计(基于问题)。这是分治法的另一种。我们将首先定义一个枚举(考虑到它仅用于unsigned int)。

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

此解决方案的运行时间与分治方法相同。

没有字符串API,没有utils,没有类型转换,只是纯java迭代->

public static int getNumberOfDigits(int input) {
    int numOfDigits = 1;
    int base = 1;
    while (input >= base * 10) {
        base = base * 10;
        numOfDigits++;
    }
    return numOfDigits;
 }

如果你愿意,你可以追求更大的价值。