如何获取整数位数?


385

是否有比此方法更整洁的方法来获取int的长度?

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

7
请定义一个int的长度。
汤姆

24
我认为他想计算数字中的数字。
2009年

3
人们给您的答案是正确的...他们给您int的长度而不将其转换为字符串...但是您为什么不想要将其转换为字符串呢?是速度的东西吗?如果是这样,我不相信这些方法会更快...您可能想要进行一些测试(或确定它是否重要。)
Beska,2009年

3
@ptomli十六进制数字仍然是数字,只是在不同的基本系统中。
Mark Pim

2
@Ptomli可以,但是在Integer.toString函数中和一般对话中,默认都是十进制。当银行告诉我“在此框中填写您的支票金额”时,我不问他们应该以十进制,十六进制还是八进制形式写。除非另有说明或上下文要求,否则我们假定为十进制。
2014年

Answers:


349

您基于String的解决方案完全可以,没有“整洁”的东西。您必须认识到,从数学上讲,数字没有长度,也没有数字。长度和数字都是特定数字(即字符串)中物理表示形式的属性。

基于对数的解决方案在内部执行(某些)基于字符串的解决方案(在某些方面),并且这样做(无关紧要)的速度更快,因为它仅产生长度并且忽略数字。但是我实际上并不会更清楚地表明其意图-这是最重要的因素。


54
在选择解决问题的方法时考虑代码的意图+1
pupeno

5
数据点:在我的机器上,log方法的运行速度似乎是字符串长度方法的两倍。如果该方法被调用很多或在代码的时间紧迫的部分中,我不会认为这无关紧要。
CPerkins,2009年

1
请参阅下面的基准测试(也可能有缺陷,我不是基准专家)。在大量运行(1000000000)中,我的机器上的速度是11s到8s,几乎没有它的两倍。
吉恩(Jean)2009年

5
@CPerkins。过早的优化。你知道那个混蛋。
Michael Borgwardt

11
一些(很晚)添加:对于负值,它可能无法正常工作,具体取决于您是否希望“-”为数字。不过,添加Math.abs()将解决此问题。
YingYang 2012年

265

对数是您的朋友:

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

注意:仅在n> 0时有效。


2
这比使用我的变体更快还是更好?
fnst

+1您击败了我一秒钟,您的回答是正确的,我的位置略有偏离。但是请注意,编译器会因缺少对int的
Dirk

2
@Tom为什么会认为它很贵?有人可能会假设数学协处理器会执行它,因此它可能接近加法的速度。即使java现在不使用协处理器,也可以假设它会...(我们只是忽略了您对Java速度慢的未经教育的暗示,因为您可能对证据不感兴趣-或如果您愿意,可以去Shootout.alioth.debian.org自己寻找)
Bill K

8
有效...除非您要检查的值= 0,否则将给您奇怪的结果(-2147483647)。Math.log10 API:“如果参数为正零或负零,则结果为负无穷大。”
mujimu

2
+1提出一种不涉及对象内存分配的方法,这是最大化重用以避免GC收集的必要条件。
Michael Wojcik 2012年

158

最快的方法:分而治之。

假设您的范围是0到MAX_INT,则您有1到10位数字。您可以使用分治法来接近此间隔,每个输入最多可进行4个比较。首先,通过一个比较将[1..10]分为[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. 基线方法(使用String.length):2145ms
  2. log10方法:711ms =基线速度的3.02倍
  3. 重复除法:2797ms =基线速度的0.77倍
  4. 分治法:74毫秒=
    基线速度的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 倍

编辑: 在编写基准测试之后,我从Java 6潜入了Integer.toString,发现它使用了:

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. 分治法:104ms
  2. Java 6解决方案-迭代和比较:406ms

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


7
这看起来很棒。?运营商获得更多的认可:你可以用它写一个小更紧凑
安德烈Pareis

88
谈论过早的优化:D
Gordon Gustafson

2
我喜欢!切换块而不是嵌套的if-elseses怎么样?
Kebman 2013年

2
我没有意识到所有这些if else语句都比将int转换为String然后调用.length快得多。+1
Ogen

15
使用三元运算符,可将其减少到101个字符: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
Jonathan Gawrych 2014年

13

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

就是说,在上述示例中,上述两种方法均无明显差异。

不论是否进行了这些修改,我得到的结果都与您截然不同。当我运行此命令时,是的,toString方法的运行时间为6400至6600毫秒,而对数方法的运行时间为20,000至20,400毫秒。对数方法对我而言不是慢一点,而是慢了3倍。

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

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

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,对数方法的1/10。

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


您是否尝试过改变输入?热点VM可能会优化该图,否则会导致基准测试错误,因为它每次都会返回相同的预计算结果。
Erik Aigner

11

使用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在开始


1
仅供参考,如果the_integeris ,将导致无穷大0,因此请检查。
埃里克·艾格纳

9

还不能发表评论,所以我将其发布为单独的答案。

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

long n = 99999999999999999L;

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

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

基于对数的解决方案以大整数计算错误的位数


尝试使用(int)(Math.log10(n + j))代替,其中j是10-(n-n / 10 * 10)。
埃里克·斯通

8

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

编辑因为我上次编辑的固定的代码示例,但没有说明。


凉。但我认为它需要abs(number),而且“ 0”也是特例吗?
2009年

是。如果您需要考虑符号,则必须执行1 +(int)Math.floor(Math.log10(Math.abs(number)))+((number <0)?1:0)
德克

5
Math.floor有点多余,是不是?强制转换为int无论如何都会舍入。
CompuChip 2014年

5

万一有人想复制并粘贴,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;
                }
            }
        }
    }
}

是否应该将此问题的标题更改为“如何获取int / long中的位数?” (并添加了'long'标签)
2012年

4

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

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

仅适用于正整数n和零。可以("" + Math.abs(n)).length()用来获取负整数的长度。
ThisClark

3

我可以试试吗?;)

基于Dirk的解决方案

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

3

普通的旧数学怎么样?除以10,直到达到0。

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

1
你测试过了吗?您知道,即使从人类的角度来看这很有意义,但它实际上与机器的“思维方式”并不相同,对吧?---让我提出一件事:最好将一个200万个数字组成一个数组Long.MAX_VALUE,这是您的代码最复杂的情​​况,并System.nanoTime()针对另一个解决方案最复杂的情​​况进行时钟试验。++实际上,仅在进行“平均复杂度”测试时,也可以将随机化器填充的数组设置为to的范围进行0尝试Long.MAX_VALUE,您可能会发现结果……非常令人震惊。
XenoRo

@thelima对于零或负数不能正常工作,但这是一个小错误。该原则在我看来是正确的。您指的是什么“震惊”结果?
周杰伦

我们只是说计算机...好吧...他们不喜欢分割。如果需要处理大量的大“队列”,并且每个处理过的数字中的每个数字都需要除法...那么...事情“开始变得非常慢而很快” ...如果您发现了含义... ---这就是为什么您在这里看到许多答案的原因,这些代码使用基于测试的代码,并使用'if'而不是除法来与每个十进制数字进行比较:如果它的速度不快,至少它可以保持大部分速度,而无论这是最坏的情况。---在大数上使用除法和对数进行测试...
XenoRo

@TheLima你在说什么?对于int,此循环,最多执行11次。您的主张有证据吗?
罗恩侯爵,2015年

@EJP从硬件的角度来看,除法是一个迭代过程。我知道最快的除法算法是radix4,它每次迭代生成4位。因此32位除法至少需要8次迭代。例如,乘法可以并行完成,也可以分解为更简单的乘法。要么降低到位级别(仅需要5次操作),要么部分分解并在末尾添加一个查找表(经典尺寸与速度折衷)。不仅仅是“多少次迭代”;除法的问题在于“每个迭代在硬件级别暗示/做了什么”
XenoRo

2

玛丽安(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)));
    }

因为我们可以。


2
有点难以理解。也许添加一些空格和/或换行符。
michaelb958--GoFundMonica

但是该死的是便携式的!
特雷弗·鲁道夫

1

很好奇,我试图对其进行基准测试...

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:115
s:788888890
运行时间2:8547
s:788888890

运行时间1:11485
s:788888890
运行时间2:8547
s:788888890

运行时间1:11469
s:788888890
运行时间2:8547
s:788888890

运行时间1:115
s:788888890
运行时间2:8547
s:788888890

运行时间1:11484
s:788888890
运行时间2:8547
s:788888890

1
只是为了好玩,从0到1万亿的数字值分布有什么区别?:)
ptomli

0

那这种递归方法呢?

    private static int length = 0;

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

0

简单的解决方案:

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

0

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

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

我不会简单地将一行称为循环。也不对10的幂进行模运算,以查看是否返回相同的值(不能仅使用比较吗?)。
Teepeemm,2015年

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

}


我不明白 好像您在回答另一个问题。
蒂普(Teepeemm)2015年

0

我还没有看到基于乘法的解决方案。对数,除法和基于字符串的解决方案在数百万个测试用例中将变得非常笨拙,因此,这里的解决方案是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 ...

不幸的是,这不能long仅通过替换int由于溢出而导致的每个实例来移植。另一方面,恰好碰巧它适用于2和10的基数(但对于其他大多数基数则严重失败)。您将需要一个查找表来查找溢出点(或除法测试... ew)

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

0

具有设计(基于问题)。这是分而治之的替代方案。我们首先定义一个枚举(考虑它仅用于一个无符号的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;
    }
}

该解决方案的运行时间与“分而治之”方法相同。


分而治之将从中间开始,并将其余的搜索区域一分为二。这具有线性运行时间。但这仅9次比较就无关紧要。但是,如果这样会不会搞砸num>=Nine.getValue()呢?
Teepeemm 2015年

0

人们之所以这样做,主要是因为他/她想“呈现”它,这主要意味着它最终需要无论如何要显式地或隐式地“ toString-ed”(或以另一种方式转换)。在展示之前(例如印刷)。

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


0

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

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

0

在查看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;
        }
    }
}

0

我看到人们使用String库甚至使用Integer类。没什么错,但是获取数字位数的算法并不那么复杂。在此示例中,我使用了long,但是使用int可以正常工作。

 private static int getLength(long num) {

    int count = 1;

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

    return count;
}

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

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


-1
    int num = 02300;
    int count = 0;
    while(num>0){
         if(num == 0) break;
         num=num/10;
         count++;
    }
    System.out.println(count);

两年前Sinista首次发布了“被10除以”的解决方案。
Teepeemm,2015年

-1

简单的递归方式

int    get_int_lenght(current_lenght, value)
{
 if (value / 10 < 10)
    return (current_lenght + 1);
return (get_int_lenght(current_lenght + 1, value))
}

未经测试


3
然后,您可能应该对其进行测试(并确保它是有效的Java并且格式正确)。但是3年前Jedi Dula发布了一种递归的“除以10”方法。
Teepeemm,2015年

-2

您可以使用连续除以十的数字:

int a=0;

if (no < 0) {
    no = -no;
} else if (no == 0) {
    no = 1;
}

while (no > 0) {
    no = no / 10;
    a++;
}

System.out.println("Number of digits in given number is: "+a);

Sinista于3年前首次发布了“除以10”的方法。这是我能想到的唯一理由。
Teepeemm,2015年

-2

输入数字并创建一个Arraylist,而while循环会将所有数字记录到中Arraylist。然后,我们可以取出数组的大小,该大小将是您输入的整数值的长度。

ArrayList<Integer> a=new ArrayList<>();

while(number > 0) 
{ 
    remainder = num % 10; 
    a.add(remainder);
    number = number / 10; 
} 

int m=a.size();

1
除非您不需要ArrayList或数字。
罗恩侯爵,2015年

-2

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

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

-3

尝试转换INT字符串,然后得到的长度字符串。那应该得到int的长度。

public static int intLength(int num){
    String n = Integer.toString(num);
    int newNum = n.length();
    return newNum;
}

这完全等同于原始代码。并在number负数时会丢失。
Teepeemm 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.