最快的逆转长 Java

huangapple go评论66阅读模式
英文:

Fastest Way To Reverse Long Java

问题

什么是反转Long值的最快方法?

例如,9876543210应返回0123456789

这是我现在有的:

long n = 0, c = 987654321 * 10; // *10用于得到9876543210作为长整型值;
while (c > 0) n = n * 10 + c % 10;
System.out.println(n);
英文:

What's the fastest way to reverse a Long value?

For example, 9876543210 should return 0123456789.

This is what I have right now:

long n = 0, c = 987654321 * 10; // *10 is to get 9876543210 as long value;
while (c > 0) n = n * 10 + c % 10;
System.out.println(n);

答案1

得分: 3

您的程序陷入了一个无限循环,因为您从未更改c的值。在每次迭代的末尾添加c /= 10,它就会工作,尽管由于它是一个数字,前导零将被删除。

long n = 0, c = 9876543210L; 
while (c > 0){
    n = n * 10 + c % 10;
    c /= 10;
}
System.out.println(n);

如果您需要保留前导零,您应该考虑使用String

long c = 9876543210L;
final StringBuilder sb = new StringBuilder();
while (c > 0){
    sb.append(c % 10);
    c /= 10;
}
System.out.println(sb.toString());
英文:

Your program encounters an infinite loop because you never change the value of c. Add c /= 10 at the end of each iteration and it will work, albeit the leading zero will be dropped due to it being a number.

long n = 0, c = 9876543210L; 
while (c > 0){
    n = n * 10 + c % 10;
    c /= 10;
}
System.out.println(n);

If you need to have the leading zero, you should consider using Strings instead.

long c = 9876543210L;
final StringBuilder sb = new StringBuilder();
while (c > 0){
    sb.append(c % 10);
    c /= 10;
}
System.out.println(sb.toString());

答案2

得分: 2

我认为这可以很快

long x = 1234567890L;
String reversed = new StringBuilder(Long.toString(x)).reverse().toString();

// reversed = "0987654321"

如果您想将反转后的值再次转换为long

long x = -1234567890000L;
StringBuilder reversed = new StringBuilder(Long.toString(x)).reverse();

System.out.println(reversed); // 0000987654321-

if (reversed.charAt(reversed.length() - 1) == '-') //删除最后位置的 `-`
{
    reversed.setLength(reversed.length() - 1);
}

while (reversed.charAt(0) == '0') //删除开头的所有 `0`
{
    reversed.replace(0, 1, "");
}

System.out.println(reversed); // 987654321

long newLong = Long.parseLong(reversed.toString());
英文:

I think this can be fast

long x = 1234567890L;
String reversed = new StringBuilder(Long.toString(x)).reverse().toString();

// reversed = "0987654321"

<hr>

If You want to convert a reversed value to a long again:

long x = -1234567890000L;
StringBuilder reversed = new StringBuilder(Long.toString(x)).reverse();

System.out.println(reversed); // 0000987654321-

if (reversed.charAt(reversed.length() - 1) == &#39;-&#39;) //remove `-` at last position
{
    reversed.setLength(reversed.length() - 1);
}

while (reversed.charAt(0) == &#39;0&#39;) //remove all `0` at the beginning 
{
    reversed.replace(0, 1, &quot;&quot;);
}

System.out.println(reversed); // 987654321

long newLong = Long.parseLong(reversed.toString());

答案3

得分: 1

您可以简单地将其转换为字符串,然后再将字符串反转,特别是如果最终希望字符串输出。这应该相当简单,而且它包括了前导的0,这也可能比为每个位置进行计算更快(但是在valueOf中进行转换的成本可能会取消这个优势):

long c = 9876543210L;
String cAsString = String.valueOf(c);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < cAsString.length(); i++) {
    builder.append(cAsString.substring(cAsString.length() - (i + 1), cAsString.length() - i));
}
System.out.println(builder.toString());

或者作为一行代码:

long c = 9876543210L;
String reverted = new StringBuilder(String.valueOf(c)).reverse().toString();
System.out.println(reverted);

我对当前答案选项进行了一些比较:

public static void main(String[] args) {
    Instant start = Instant.now();
    for (long i = 0; i < 100_000_000; i++) {
        stringbuilderWithDirectCalcs(i);
    }
    Duration duration = Duration.between(start, Instant.now());
    System.out.println("Took " + duration);
}

protected static void stringbuilderWithDirectCalcs(long value) {
    final StringBuilder sb = new StringBuilder();
    while (value > 0) {
        sb.append(value % 10);
        value /= 10;
    }
    // System.out.println(sb.toString());
}

protected static void stringbuilderConvenient(long value) {
    String reverted = new StringBuilder(String.valueOf(value)).reverse().toString();
    //System.out.println(reverted);
}

protected static void stringbuilderHandCrafted(long value) {
    String cAsString = String.valueOf(value);
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < cAsString.length(); i++) {
        builder.append(cAsString.substring(cAsString.length() - (i + 1), cAsString.length() - i));
    }
    //System.out.println(builder.toString());
}

我进行了三次运行。结果如下:

stringbuilderConvenient
Took PT6.988S / Took PT6.8S / Took PT6.68S

stringbuilderWithDirectCalcs:
Took PT6.17S / Took PT6.776S / Took PT6.692S

stringbuilderHandCrafted
Took PT18.205S / Took PT16.035S / Took PT17.025S

因此,手动扫描字符串并逐步组装StringBuilder似乎不可行。显然,Stephen C在他的评论中是对的,即在转换为String时计算仍然会发生。但基于StringBuilder.reverse和手动计算每个位置的方法非常接近(任何差异可能是由于微小的运行时波动引起的)。因此,人们可以选择StringBuilder.reverse方法,以提高可读性,性能几乎相同。

英文:

You can simply convert to string and then revert the String, in particular if you want string output in the end anyway. This should be quite straight forward and it has the leading 0, it might also be faster than doing calculations for each positions (but the cost of conversion in valueOf might cancel that advantage):

    long c = 9876543210L;
    String cAsString = String.valueOf(c);
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i &lt; cAsString.length(); i++) {
        builder.append(cAsString.substring(cAsString.length() - (i + 1), cAsString.length() - i));
    }
    System.out.println(builder.toString());

or as a one liner

    long c = 9876543210L;
    String reverted = new StringBuilder(String.valueOf(c)).reverse().toString();
    System.out.println(reverted);

I did a little comparison between the options of the current answers:

    public static void main(String[] args) {
    Instant start = Instant.now();
    for (long i = 0; i &lt; 100_000_000; i++) {
        stringbuilderWithDirectCalcs(i);
    }
    Duration duration = Duration.between(start, Instant.now());
    System.out.println(&quot;Took &quot; + duration);
}


protected static void stringbuilderWithDirectCalcs(long value) {
    final StringBuilder sb = new StringBuilder();
    while (value &gt; 0) {
        sb.append(value % 10);
        value /= 10;
    }
    // System.out.println(sb.toString());
}


protected static void stringbuilderConvenient(long value) {
    String reverted = new StringBuilder(String.valueOf(value)).reverse().toString();
    //System.out.println(reverted);
}


protected static void stringbuilderHandCrafted(long value) {
    String cAsString = String.valueOf(value);
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i &lt; cAsString.length(); i++) {
        builder.append(cAsString.substring(cAsString.length() - (i + 1), cAsString.length() - i));
    }
    //System.out.println(builder.toString());
}

I did three runs each. The outcome:

stringbuilderConvenient
Took PT6.988S /  Took PT6.8S / Took PT6.68S


stringbuilderWithDirectCalcs:
Took PT6.17S / Took PT6.776S / Took PT6.692S


stringbuilderHandCrafted
Took PT18.205S / Took PT16.035S / Took PT17.025S

So, scanning the String by hand and sticking the StringBuilder together step by step seems out of the question. Obviously Stephen C was right in his comment that the calculations happen anyway when converting to String. But the approach based on Stringbuilder.reverse and handcalculating each position are pretty close (and any difference might be due to minor runtime fluctuations). So, one might choose the StringBuilder.reverse method over calculating each position by hand for readability with about the same performance.

huangapple
  • 本文由 发表于 2020年8月4日 06:55:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/63238003.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定