Concepts / Converting Strings to Numbers

Converting Strings to Numbers

NumberFormatException occurs when a string is not a legal representation of a number, as in Integer.parseInt("fred"), and Double.parseDouble can also throw it.

  • Programming
Interactive lab

Try it: try / except / else / finally

How an exception jumps out of a try block to the first matching except clause, when else runs, and why finally always runs.

How it works

  1. Statements in try run until one raises an exception; the rest of try is skipped.
  2. Python checks the except clauses in order and runs the first one whose type matches.
  3. If nothing was raised, the else block runs instead.
  4. finally runs in every case.

Default run (9 steps): Call safe_divide('4'). … Return 25.0. Output was: Worked: 25.0 / Done.

Simplified: One fixed function; int() and / are modelled exactly (including how Python prints floats), but nothing is executed as Python.

Educational simulation

Loading the simulation…

Where Program Data Starts as Text

Many programs receive their data as text. A user types something into a box, a file supplies a line of characters, or a web form sends a field as a String. When the program needs a number from that text, it has to convert the string into a numeric value. Sometimes that conversion succeeds, and sometimes it cannot be carried out at all. This article follows one conversion call through both of its possible outcomes and then looks at a second, unrelated kind of exception that can appear in the same situations.

What do you think happens?

Suppose str holds the text fred. What happens when Integer.parseInt(str) runs?

  • It returns 0

  • It returns the number of letters in fred

  • It throws a NumberFormatException

Reveal answer
Answer:

It throws a NumberFormatException

The text fred is not a legal representation of an integer, so the conversion cannot be carried out. The source uses exactly this call, Integer.parseInt("fred"), as its example of the failure.

One Call, Two Possible Outcomes

Consider the function call Integer.parseInt(str), where str is a variable of type String. The result depends entirely on what the string contains. The same line of code can produce a number or an exception, and nothing in the call itself tells you which will happen. The contents of the string decide.

When the string is a legal representation of an integer, such as the text 42, the conversion works and the method returns the number 42. When the string is not a legal representation of a number, such as fred, the method throws a NumberFormatException instead of returning a value. An exception is a signal that something has gone wrong during execution, and it interrupts the normal flow of the program at the point where it is raised.

String passed infor example 42 or fredLegal number text?Number returnedfor example 42Handled by writtencodeNumberFormatExceptionfor example fredProgram crashesif unhandledchecked once per callyesnocaughtnot caught
Starting from a string passed to Integer.parseInt or Double.parseDouble, which path does execution take to a returned number, and which path leads to an exception that either crashes the program or is handled?

Read the diagram as a decision made once per call. The string either satisfies the rules for a legal number or it does not. A legal string leads to a returned value. An illegal string leads to the exception. From there, the exception either goes unhandled, in which case the program crashes, or it is handled by code the programmer has written. The source describes the unhandled case directly: if nothing is done to handle the exception, the program will crash.

Tracing a Successful and a Failing Conversion

java
Output
43
Notes on the code
  • The string 42 is a legal representation of an integer, so parseInt returns the number 42.
  • The returned value is stored in n and used like any other int.
Worked example

Following the failing case

A variable holds the text fred and the program calls Integer.parseInt on it. Trace what happens to the normal flow of the program.

  1. 1
    Call the method

    Integer.parseInt(str) runs with str equal to fred.

  2. 2
    Check the text

    fred is not a legal representation of an integer, so no number can be produced.

  3. 3
    Raise the exception

    The method throws a NumberFormatException, and the normal flow of the program is interrupted at this line.

  4. 4
    Look for handling

    If no code deals with the exception, the program crashes. If written code catches it, that code decides what happens next.

Result

The call produces no number. The program either crashes or continues only because the programmer wrote code to deal with the exception.

Double.parseDouble works in the same way. It can also throw a NumberFormatException when it receives a string that is not a valid representation of a double. The exception has the same name in both cases because both functions convert text into a number and both can fail when the text is malformed. If you remember the rule for one, you should expect the other to fail for the same underlying reason, a string that is not a legal number.

Handling a NumberFormatException

Because a NumberFormatException interrupts the program, a careful programmer writes code that anticipates it. The source does not prescribe a specific technique, but the general idea is that the code around the conversion decides what to do when the text is not a legal number. The programmer might report the problem to the user, ask for the input again, or use a default. The important point from the source is that the exception does not fix itself. Without that handling, the program crashes.

java
Output
That is not a whole number.
Notes on the code
  • The conversion is placed inside a try block, so the program can react to a failure.
  • The catch block runs only when parseInt throws a NumberFormatException, and this is the programmer's choice of response.

Where an IllegalArgumentException Comes From

The second kind of exception has a different cause. An IllegalArgumentException can occur when an illegal value is passed as a parameter to a subroutine. The problem is not in converting text. The problem is that the value handed to the subroutine is not one the subroutine accepts. The source gives the typical case: if a subroutine requires that a parameter be greater than or equal to zero, an IllegalArgumentException might occur when a negative value is passed to it.

Tracing an IllegalArgumentException Up the Call Stack

The diagram below shows a three-level chain of subroutine calls. The main method calls a computing subroutine, which passes a negative value to a subroutine that requires a non-negative parameter. That subroutine raises the exception. Each frame in the chain is still active when the exception is raised, and the exception moves back up through those frames until some code handles it or none does.

main methodfirst framecomputeRatepasses -5 onwardsetRate subroutinethrowsIllegalArgumentExceptioncallscalls with -5
When a subroutine throws IllegalArgumentException, which caller frames are on the stack, and which one decides whether the program crashes or recovers?

In the diagram, the setRate subroutine is the frame that detects the illegal value and raises the exception. The exception then travels back toward the frames that called it, computeRate and then main. Whether the program crashes or recovers depends on what those frames contain. If none of them has code that handles the exception, the program crashes. If one of them has handling code, that frame decides how the program responds. The source's point that the response is decided by the subroutine's author applies here: the author of setRate decided to raise the exception, and the authors of the calling code decide whether to handle it.

Telling the Two Exceptions Apart

Both exceptions signal that a value was not acceptable, but they arise from different situations. The table sets the two side by side so that their causes can be compared directly. The key question for each is where the bad value came from and what kind of check failed.

FeatureNumberFormatExceptionIllegalArgumentException
Typical triggerInteger.parseInt("fred") or Double.parseDouble on malformed textA subroutine receives an illegal parameter, such as a negative value where a non-negative one is required
Where the problem isIn the text being converted to a numberIn the value passed into a subroutine
What went wrongThe string is not a legal representation of a numberThe value is not one the subroutine accepts
Is the response fixed?Without handling, the program crashesThe response is decided by the subroutine's author, so it is a common response rather than a guaranteed one

Causes of the two exceptions described in the source

Mistakes Learners Often Make

  • Common mistake

    Assuming a failed conversion quietly returns zero

    What it looks like
    Integer.parseInt("fred") is expected to return 0.
    Why it fails

    The source states that the illegal string causes a NumberFormatException to be thrown, not that a default value is returned.

    Do this instead

    Expect an exception, and write code that handles it if the program should continue.

  • Common mistake

    Treating both exceptions as the same kind of problem

    Why it fails

    NumberFormatException comes from the text being converted, while IllegalArgumentException comes from an illegal parameter passed to a subroutine.

    Do this instead

    Ask whether the bad value was text that could not become a number, or a value a subroutine refused to accept.

  • Common mistake

    Assuming an IllegalArgumentException always happens for a bad parameter

    Why it fails

    The source says the response to an illegal parameter is decided by the subroutine's author, so it is not guaranteed.

    Do this instead

    Check the documentation or the code of the subroutine to see how it responds to illegal input.

  • Common mistake

    Leaving a conversion unprotected in a program that must keep running

    Why it fails

    If nothing handles the exception, the program crashes.

    Do this instead

    Place handling code around conversions whose input could be malformed.

Checking Your Understanding of Conversion Outcomes

EASY

A program calls Integer.parseInt on the text 42 and then on the text fred. For each call, state whether a number is returned or a NumberFormatException is thrown, and explain what determines which outcome occurs.

Hints
  • Look at whether the string is a legal representation of a number.
  • The contents of the string decide the outcome, not the method name.
MEDIUM

A subroutine named setRate requires its parameter to be greater than or equal to zero. Another method passes it the value -5. Which exception describes this situation, and which part of the program decides whether the program crashes?

Hints
  • The bad value is a parameter to a subroutine, not text being converted.
  • The source says the response is decided by the subroutine's author and that the program crashes if nothing handles the exception.

Key Takeaways

  • Integer.parseInt and Double.parseDouble return a number for a legal string such as 42, but throw a NumberFormatException for a string such as fred that is not a legal representation of a number.
  • A NumberFormatException comes from the text being converted; if no code handles it, the program crashes.
  • An IllegalArgumentException comes from an illegal parameter passed to a subroutine, such as a negative value where a non-negative one is required.
  • The response to an illegal parameter is decided by the subroutine's author, so IllegalArgumentException is a common response rather than a guaranteed one.