方法获得数字在一个int?

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

int numDigits = String.valueOf(1000).length();
681462 次浏览

对数是你的朋友:

int n = 1000;
int length = (int)(Math.log10(n)+1);

NB:只对n >有效0。

由于以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);
}
}

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

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

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

我能试试吗?;)

基于德克的解决方案

final int digits = number==0?1:(1 + (int)Math.floor(Math.log10(Math.abs(number))));

出于好奇,我试着对其进行基准测试……

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




}
}

结果如下:

Run time 1: 6765
s: 400000000
Run time 2: 6000
s: 400000000

现在我想知道我的基准测试是否真的意味着什么,但我确实在基准测试本身的多次运行中得到了一致的结果(一毫秒内的变化)……:)看起来这是无用的尝试和优化…


编辑:根据ptomli的注释,我在上面的代码中用' I '替换'number',并在5次运行的bench中得到以下结果:

Run time 1: 11500
s: 788888890
Run time 2: 8547
s: 788888890


Run time 1: 11485
s: 788888890
Run time 2: 8547
s: 788888890


Run time 1: 11469
s: 788888890
Run time 2: 8547
s: 788888890


Run time 1: 11500
s: 788888890
Run time 2: 8547
s: 788888890


Run time 1: 11484
s: 788888890
Run time 2: 8547
s: 788888890

关于你的基准测试有两个评论:Java是一个复杂的环境,有即时编译和垃圾收集等等,所以为了得到一个公平的比较,每当我运行一个基准测试时,我总是:(a)将两个测试放在一个循环中,按顺序运行5或10次。通常情况下,第二次循环时的运行时与第一次完全不同。(b)在每个“方法”之后,我执行System.gc()来尝试触发垃圾收集。否则,第一种方法可能会生成一堆对象,但还不足以强制进行垃圾收集,然后第二种方法创建一些对象,堆耗尽,垃圾收集运行。然后第二种方法被“收费”,因为它要清除第一种方法留下的垃圾。很不公平!

也就是说,上述两种方法在本例中都没有产生显著差异。

不管有没有这些修改,我得到的结果和你完全不同。当我运行这个时,是的,toString方法给出的运行时间为6400到6600 millis,而log方法给出的运行时间为20,000到20,400 millis。对数方法对我来说不是稍微快一点,而是慢了3倍。

请注意,这两种方法涉及非常不同的代价,所以这并不完全令人震惊:toString方法将创建许多必须清理的临时对象,而log方法需要更密集的计算。因此,可能区别在于,在内存较少的机器上,toString需要更多的垃圾收集回合,而在处理器较慢的机器上,额外的log计算将更加痛苦。

我还尝试了第三种方法。我写了这个小函数:

static int numlength(int n)
{
if (n == 0) return 1;
int l;
n=Math.abs(n);
for (l=0;n>0;++l)
n/=10;
return l;
}

在我的机器上,它运行在1600到1900毫厘之间——不到toString方法的1/3,log方法的1/10。

如果您的数字范围很广,您可以通过开始除以1000或1,000,000来进一步加快速度,以减少循环的次数。我还没玩过。

最快的方法:分而治之。

假设你的范围是0到MAX_INT,那么你有1到10个数字。您可以使用分治法来接近这个间隔,每个输入最多4个比较。首先,除以[1..10] into [1.]5]和[6..10]和一个比较,然后每个长度5间隔你用一个比较分为一个长度3和一个长度2间隔。长度为2的区间需要再进行一次比较(共3次比较),长度为3的区间可以分为长度为1的区间(解)和长度为2的区间。所以你需要3到4个比较。

没有除法,没有浮点运算,没有昂贵的对数,只有整数比较。

代码(长但快):

if (n < 100000) {
// 5 or less
if (n < 100){
// 1 or 2
if (n < 10)
return 1;
else
return 2;
} else {
// 3 or 4 or 5
if (n < 1000)
return 3;
else {
// 4 or 5
if (n < 10000)
return 4;
else
return 5;
}
}
} else {
// 6 or more
if (n < 10000000) {
// 6 or 7
if (n < 1000000)
return 6;
else
return 7;
} else {
// 8 to 10
if (n < 100000000)
return 8;
else {
// 9 or 10
if (n < 1000000000)
return 9;
else
return 10;
}
}
}

基准测试(在JVM预热之后)——查看下面的代码以了解基准测试是如何运行的:

  1. 基线方法(with String.length): 李女士2145年< / >
  2. log10方法:711ms = 3.02次 快如基线
  3. 重复除:2797ms = 0.77次 快如基线
  4. 分治:74ms = 28.99
    倍于基线

完整的代码:

public static void main(String[] args) throws Exception {
    

// validate methods:
for (int i = 0; i < 1000; i++)
if (method1(i) != method2(i))
System.out.println(i);
for (int i = 0; i < 1000; i++)
if (method1(i) != method3(i))
System.out.println(i + " " + method1(i) + " " + method3(i));
for (int i = 333; i < 2000000000; i += 1000)
if (method1(i) != method3(i))
System.out.println(i + " " + method1(i) + " " + method3(i));
for (int i = 0; i < 1000; i++)
if (method1(i) != method4(i))
System.out.println(i + " " + method1(i) + " " + method4(i));
for (int i = 333; i < 2000000000; i += 1000)
if (method1(i) != method4(i))
System.out.println(i + " " + method1(i) + " " + method4(i));
    

// work-up the JVM - make sure everything will be run in hot-spot mode
allMethod1();
allMethod2();
allMethod3();
allMethod4();
    

// run benchmark
Chronometer c;
    

c = new Chronometer(true);
allMethod1();
c.stop();
long baseline = c.getValue();
System.out.println(c);
    

c = new Chronometer(true);
allMethod2();
c.stop();
System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");
    

c = new Chronometer(true);
allMethod3();
c.stop();
System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");
    

c = new Chronometer(true);
allMethod4();
c.stop();
System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");
}




private static int method1(int n) {
return Integer.toString(n).length();
}


private static int method2(int n) {
if (n == 0)
return 1;
return (int)(Math.log10(n) + 1);
}


private static int method3(int n) {
if (n == 0)
return 1;
int l;
for (l = 0 ; n > 0 ;++l)
n /= 10;
return l;
}


private static int method4(int n) {
if (n < 100000) {
// 5 or less
if (n < 100) {
// 1 or 2
if (n < 10)
return 1;
else
return 2;
} else {
// 3 or 4 or 5
if (n < 1000)
return 3;
else {
// 4 or 5
if (n < 10000)
return 4;
else
return 5;
}
}
} else {
// 6 or more
if (n < 10000000) {
// 6 or 7
if (n < 1000000)
return 6;
else
return 7;
} else {
// 8 to 10
if (n < 100000000)
return 8;
else {
// 9 or 10
if (n < 1000000000)
return 9;
else
return 10;
}
}
}
}




private static int allMethod1() {
int x = 0;
for (int i = 0; i < 1000; i++)
x = method1(i);
for (int i = 1000; i < 100000; i += 10)
x = method1(i);
for (int i = 100000; i < 1000000; i += 100)
x = method1(i);
for (int i = 1000000; i < 2000000000; i += 200)
x = method1(i);
    

return x;
}


private static int allMethod2() {
int x = 0;
for (int i = 0; i < 1000; i++)
x = method2(i);
for (int i = 1000; i < 100000; i += 10)
x = method2(i);
for (int i = 100000; i < 1000000; i += 100)
x = method2(i);
for (int i = 1000000; i < 2000000000; i += 200)
x = method2(i);
    

return x;
}


private static int allMethod3() {
int x = 0;
for (int i = 0; i < 1000; i++)
x = method3(i);
for (int i = 1000; i < 100000; i += 10)
x = method3(i);
for (int i = 100000; i < 1000000; i += 100)
x = method3(i);
for (int i = 1000000; i < 2000000000; i += 200)
x = method3(i);
    

return x;
}


private static int allMethod4() {
int x = 0;
for (int i = 0; i < 1000; i++)
x = method4(i);
for (int i = 1000; i < 100000; i += 10)
x = method4(i);
for (int i = 100000; i < 1000000; i += 100)
x = method4(i);
for (int i = 1000000; i < 2000000000; i += 200)
x = method4(i);
    

return x;
}

基准:

  1. 基线方法(String.length): 2145ms
  2. Log10方法:711ms =基线速度的3.02倍
  3. 重复除:2797ms =基线速度的0.77倍
  4. 分治:74毫秒= 28.99倍的基线速度

编辑

在我写完基准测试之后,我偷偷地看了一下Integer。toString来自Java 6,我发现它使用:

final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };


// Requires positive x
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}

我以我的分治方案为基准:

  1. 分治法:104毫秒
  2. Java 6解决方案-迭代和比较:406ms

我的速度大约是Java 6解决方案的4倍。

Marian的解决方案适用于类型的数字(高达9,223,372,036,854,775,807),以防有人想要复制粘贴它。 在程序中,我写了这个,因为10000以内的数字更有可能,所以我为它们做了一个特定的分支。不管怎样,它不会有显著的区别

public static int numberOfDigits (long n) {
// Guessing 4 digit numbers will be more probable.
// They are set in the first branch.
if (n < 10000L) { // from 1 to 4
if (n < 100L) { // 1 or 2
if (n < 10L) {
return 1;
} else {
return 2;
}
} else { // 3 or 4
if (n < 1000L) {
return 3;
} else {
return 4;
}
}
} else  { // from 5 a 20 (albeit longs can't have more than 18 or 19)
if (n < 1000000000000L) { // from 5 to 12
if (n < 100000000L) { // from 5 to 8
if (n < 1000000L) { // 5 or 6
if (n < 100000L) {
return 5;
} else {
return 6;
}
} else { // 7 u 8
if (n < 10000000L) {
return 7;
} else {
return 8;
}
}
} else { // from 9 to 12
if (n < 10000000000L) { // 9 or 10
if (n < 1000000000L) {
return 9;
} else {
return 10;
}
} else { // 11 or 12
if (n < 100000000000L) {
return 11;
} else {
return 12;
}
}
}
} else { // from 13 to ... (18 or 20)
if (n < 10000000000000000L) { // from 13 to 16
if (n < 100000000000000L) { // 13 or 14
if (n < 10000000000000L) {
return 13;
} else {
return 14;
}
} else { // 15 or 16
if (n < 1000000000000000L) {
return 15;
} else {
return 16;
}
}
} else { // from 17 to ...¿20?
if (n < 1000000000000000000L) { // 17 or 18
if (n < 100000000000000000L) {
return 17;
} else {
return 18;
}
} else { // 19? Can it be?
// 10000000000000000000L is'nt a valid long.
return 19;
}
}
}
}
}

那简单的数学呢?除以10,直到0。

public static int getSize(long number) {
int count = 0;
while (number > 0) {
count += 1;
number = (number / 10);
}
return count;
}

这个递归方法呢?

    private static int length = 0;


public static int length(int n) {
length++;
if((n / 10) < 10) {
length++;
} else {
length(n / 10);
}
return length;
}

简单的解决方案:

public class long_length {
long x,l=1,n;
for (n=10;n<x;n*=10){
if (x/n!=0){
l++;
}
}
System.out.print(l);
}

这是我做的一个非常简单的方法,适用于任何数字:

public static int numberLength(int userNumber) {


int numberCounter = 10;
boolean condition = true;
int digitLength = 1;


while (condition) {
int numberRatio = userNumber / numberCounter;
if (numberRatio < 1) {
condition = false;
} else {
digitLength++;
numberCounter *= 10;
}
}


return digitLength;
}

它的工作方式是使用数字计数器变量,即10 = 1位空格。例如。1 = 1十分之一=> 1位空格。因此,如果你有int number = 103342;,你会得到6,因为这相当于返回。000001空格。还有,谁有更好的numberCounter变量名?我想不出比这更好的了。

编辑:我想到了一个更好的解释。本质上,这个while循环所做的就是让你的数字除以10,直到它小于1。从本质上讲,当你把一个数除以10时,你是在把它向后移动一个数字空间,所以你只需把它除以10,直到你的数字中的位数达到<1。

下面是另一个版本,可以计算小数中的数字数量:

public static int repeatingLength(double decimalNumber) {


int numberCounter = 1;
boolean condition = true;
int digitLength = 1;


while (condition) {
double numberRatio = decimalNumber * numberCounter;


if ((numberRatio - Math.round(numberRatio)) < 0.0000001) {
condition = false;
} else {
digitLength++;
numberCounter *= 10;
}
}
return digitLength - 1;
}

玛丽安的解决方案,现在是三元:

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

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

或者相反,你可以检查这个数字是否大于或小于所需的数字。

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

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

现在还不能留言,所以我会单独回复。

基于对数的解决方案不能计算非常大的长整数的正确位数,例如:

long n = 99999999999999999L;


// correct answer: 17
int numberOfDigits = String.valueOf(n).length();


// incorrect answer: 18
int wrongNumberOfDigits = (int) (Math.log10(n) + 1);

基于对数的解决方案计算大整数中不正确的位数

我们可以使用递归循环来实现这一点

    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+"]");
}

一个人想要这样做主要是因为他/她想要“呈现”它,这主要意味着它最终需要显式或隐式地“toString-ed”(或以另一种方式转换);才能呈现(例如打印出来)。

如果是这种情况,那么只需尝试显式地使用必要的“toString”并计算位数。

使用Java

int nDigits = Math.floor(Math.log10(Math.abs(the_integer))) + 1;

开始时使用import java.lang.Math.*;

使用C

int nDigits = floor(log10(abs(the_integer))) + 1;

开始时使用inclue math.h

另一种字符串方法。简短而甜蜜-适用于任何整数n

int length = ("" + n).length();

我在看了Integer.java源代码后写了这个函数。

private static int stringSize(int x) {
final int[] sizeTable = {9, 99, 999, 9_999, 99_999, 999_999, 9_999_999,
99_999_999, 999_999_999, Integer.MAX_VALUE};
for (int i = 0; ; ++i) {
if (x <= sizeTable[i]) {
return i + 1;
}
}
}

我看到有人使用String库,甚至使用Integer类。这没什么问题,但是求位数的算法并不复杂。我在这个例子中使用的是long类型,但它也可以用于int类型。

 private static int getLength(long num) {


int count = 1;


while (num >= 10) {
num = num / 10;
count++;
}


return count;
}

没有字符串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;
}

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

计算int变量中位数的有效方法之一是定义一个方法digitsCounter,该方法具有所需数量的条件语句。
方法很简单,我们将检查n数字可以位于的每个范围:
0: 9Single数字
10:99Double数字
100: 999Triple数字,等等…

    static int digitsCounter(int N)
{   // N = Math.abs(N); // if `N` is -ve
if (0 <= N && N <= 9) return 1;
if (10 <= N && N <= 99) return 2;
if (100 <= N && N <= 999) return 3;
if (1000 <= N && N <= 9999) return 4;
if (10000 <= N && N <= 99999) return 5;
if (100000 <= N && N <= 999999) return 6;
if (1000000 <= N && N <= 9999999) return 7;
if (10000000 <= N && N <= 99999999) return 8;
if (100000000 <= N && N <= 999999999) return 9;
return 10;
}

一种更干净的方法是取消下限检查,因为如果我们按顺序进行,就不需要下限检查了。

    static int digitsCounter(int N)
{
N = N < 0 ? -N : N;
if (N <= 9) return 1;
if (N <= 99) return 2;
if (N <= 999) return 3;
if (N <= 9999) return 4;
if (N <= 99999) return 5;
if (N <= 999999) return 6;
if (N <= 9999999) return 7;
if (N <= 99999999) return 8;
if (N <= 999999999) return 9;
return 10; // Max possible digits in an 'int'
}

理想情况下,一个整数除以10的倍数将返回位数,只要该整数不为零。这样一个简单的方法可以创建如下所示。

public static int getNumberOfDigits(int number) {
int numberOfDigits = 0;
while(number != 0) {
number /= 10;
numberOfDigits++;
}
    

return numberOfDigits;
}

这取决于你对“整洁”的定义。我认为下面的代码相当简洁,运行速度也很快。

它基于玛丽安的 回答,扩展到所有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;
}

下面是JDK开发人员给出的解决方案。JDK 17(类Long):

/**
* Returns the string representation size for a given long value.
*
* @param x long value
* @return string size
*
* @implNote There are other ways to compute this: e.g. binary search,
* but values are biased heavily towards zero, and therefore linear search
* wins. The iteration results are also routinely inlined in the generated
* code after loop unrolling.
*/
static int stringSize(long x) {
int d = 1;
if (x >= 0) {
d = 0;
x = -x;
}
long p = -10;
for (int i = 1; i < 19; i++) {
if (x > p)
return i + d;
p = 10 * p;
}
return 19 + d;
}

注意,如果需要的话,该方法会考虑减号。

不幸的是,该方法没有公开。

在性能方面,你可以从评论中看到,JDK开发人员与其他选项相比至少考虑了这一点。我猜 分而治之的方法倾向于较小的数字,效果会稍好一些 更好,因为CPU可以比整数更快地进行整数比较 乘法。但差异可能小到无法测量

无论如何,我希望JDK中已经公开了这个方法,这样人们就不会开始使用自己的方法了。