简体   繁体   中英

Why is my program throwing a StringIndexOutOfBounds exception?

I am writing a program to calculate:

1^1 + 2^2 + 3^3 + ... + 1000^1000 = ?

Once it has calculated it I want to remove all of the digits in the answer besides the last ten digits, and then print the final ten digits on the screen. To remove all of the other digits I am using the StringBuilder.deleteCharAt() method, however, this is causing me some problems. I have provided my code below:

import java.math.BigInteger;
public class problemFourtyEight {
  public static void main(String [] args) {
    BigInteger answer = new BigInteger(""+0);
    for(int i = 0; i <= 1000; i++) {
      BigInteger temp = new BigInteger(""+i);
      temp = temp.pow(i);
      answer = answer.add(temp);
    }
    System.out.println(answer.toString().length());
    StringBuilder sb = new StringBuilder((answer.toString()));
    for(int k = 0; k <= (answer.toString().length() - 10); k++) {
      sb.deleteCharAt(k);  //Line 13 is here.
    }
    String finalAnswer = sb.toString();
    System.out.println(finalAnswer);
  }
}

The exception thrown is:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 1501
    at java.lang.AbstractStringBuilder.deleteCharAt(AbstractStringBuilder.java:797)
    at java.lang.StringBuilder.deleteCharAt(StringBuilder.java:253)
    at problemFourtyEight.main(problemFourtyEight.java:13)

From printing out the length of the answer (before removing any characters), it tells me the length of the number is 3001, so I can't understand why the String index 1,501 is said to be OutOfBounds .

Your error is that this code:

StringBuilder sb = new StringBuilder((answer.toString()));
for(int k = 0; k <= (answer.toString().length() - 10); k++) {
  sb.deleteCharAt(k);  //Line 13 is here.
}

Makes the string shorter as it goes, due to the mutability of string builder. You want:

System.out.println(answer.substring(answer.length()-10))

This also has the advantage of speed, if that matters to you.

When you delete the i'th character, the i+1'th character becomes the new i'th character. Therefore, your look should always remove the first character :

for(int k = 0; k <= (answer.toString().length() - 10); k++) {
  sb.deleteCharAt(0);
}

For example :

        StringBuilder sb = new StringBuilder("abcdef");
        sb.deleteCharAt(0);
        sb.deleteCharAt(1);
        sb.deleteCharAt(2);
        sb.deleteCharAt(3); // throws java.lang.StringIndexOutOfBoundsException: String index out of range: 3
        System.out.println(sb.toString());

        sb = new StringBuilder("abcdef");
        sb.deleteCharAt(0);
        sb.deleteCharAt(0);
        sb.deleteCharAt(0);
        sb.deleteCharAt(0);
        System.out.println(sb.toString()); // prints "ef"

This code might work (somewhat) if you checked the length of your StringBuilder object, but as-is you check the length of the original string, but delete characters from the StringBuilder . The StringBuilder gets shorter each time you delete, so eventually the k index is out of bounds for the sb .

StringBuilder sb = new StringBuilder((answer.toString()));
for(int k = 0; k <= (sb.length() - 10); k++) { // <-- make sure to test the length of the thing you are mutating
  sb.deleteCharAt(0);  // Delete first character of remaining sb
}

But yes, substring() should be much preferred here.

I think it is because every time you remove a character from the string the string buffer resizes and your string becomes shorter, so after deleting 1500 characters from 3001 your string buffer is storing chars from 0 to 1500 and the index 1501 is out of range.

You can use substring to print the last 10 digits.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM