# How to Convert a String to a Number in JavaScript? Integers, Floats, Big Numbers, and Edge Cases Explained.

This article is a deep dive into the wacky world of number conversion in JavaScript. (And it only scratches the surface.) The method you’ll use will greatly depend on the type of data you’re working with. For example:

• Are these just integers or can they be decimal (float) numbers?
• How big can these numbers be? How small can they be?
• Are they base 10 (decimal) numbers, or are you dealing with a different base like hexadecimal?
• What about `Infinity`? How do you want to handle `NaN`?
• What about different formatting types based on language?

## The Number Constructor

Just providing the string to the `Number` constructor might be enough for your use case. Examples:

``````Number("123") // => 123
Number("-123") // => -123
Number("123.45") // => 123.45 (floating point number)
Number("12e5") // => 1200000
Number("0.12e-5") // => 0.0000012
Number("Infinity") // => Infinity
``````

But there’s also some interesting edge cases:

``````Number("12e") // => NaN
Number("123,000") // => NaN
Number("") // => 0 (this one is very dangerous!)
``````

This method is attractive because of the versitility, but also very dangerous. Be sure to cover your code with unit tests so edge cases don’t slip through!

## Using `parseInt` and Handling Different Bases (Radix)

`parseInt` is a built-in JavaScript function that parses a string argument and returns an integer of the specified base (radix). If you know you are only dealing with integers, this is your best best.

``````parseInt("123") // => 123
parseInt("-123") // => -123
``````

The method has a second parameter, which is `10` by default, indicating that the conversion should be base 10. But you can change this:

``````parseInt("fff", 16) // => 4095
parseInt("0101", 2) // => 5
``````

Things that are not integers, will end up being converted to `NaN`:

``````parseInt("Infinity") // => NaN
parseInt("") // => NaN
``````

But you should be aware of these edge cases:

``````parseInt("123.45") // => 123
parseInt("123,000") // => 123
parseInt("12e5") // => 12
``````

## Making Floats with `parseFloat`

I hope that whatever you’re doing with floats is managable, because these can become quite a nightmare. Here’s some examples of what you can expect:

``````parseFloat("123") // => 123
parseFloat("-123") // => -123
parseFloat("123.300") // => 123.3
parseFloat("12e5") // => 1200000
parseFloat("12e-5") // => 0.00012
parseFloat("123,300") // => 123
parseFloat("123,300.00") // => 123
parseFloat("Infinity") // => Infinity
paeseFloat("") // => NaN
``````

Two questions arise here:

1. What is the level of precision?
2. How do you handle different locales? Some might format the number `123456` as `123,456.00` and others `123.456,00`, depending on the country.

### Precision and `toPrecision`

As you may have figured out by now all JavaScript numbers are the same `Number` type. There is no special `float` data type. All numbers are internally stored in double-precision 64-bit binary format IEEE 754. (Just like `double` in Java or C#.) The `Number` type keeps `17` decimal places of precision. The largest value a Number can hold is about `2^53 -1`. This value is represented by the constant `Number.MAX_SAFE_INTEGER`. (Another lie, since it’s not actually an integer.) You can check this yourself:

``````Math.pow(2, 53) - 1 === Number.MAX_SAFE_INTEGER // => true
``````

If you need to format your number to a set precission, the `toPrecision` method is there:

``````const a = 123.456
console.log(a.toPrecision(10)) // => "123.4560000"
``````

### Different Locales

Unfortunetly, there is no built-in way to distinguish between different locales when it comes to parsing numbers. You will have to look in userland for libraries that accomplish this task.

## BigInt

Need to represent really, really big numbers? You can use the `BigInt` object or just append `n` to an integer to cast it into this type. Examples:

``````const hugeNum1 = BigInt("904240240249024902094290407199254740991");
const hugeNum2 = 904240240249024902094290407199254740991n;
hugeNum1 === hugeNum2 // => true
typeof hugeNum1 === 'bigint' && typeof hugeNum2 === 'bigint' // => true
``````

### BigInt Comparison and Equality

But also note that there some interesting things when trying to compare BigInt with numbers. For example, strict equality comparison will fail, while loose comparison can succeed:

``````const num = 0;
const bigNum = 0n;
num1 === bigNum // => false, they are not of the same type!
num == bigNum // => true, once cast to the same type their values are equal
``````

Other comparison operations work as expected:

``````0n < 1 // true
1n > 0 // true
2n > 2 // false
2n < 2 // false
``````

### BigInt and Sorting

Since the above operations work as expected, it is possible to sort an array of BitInts using the default behaviour of `Array.sort`. It’s also possible to sort a mixed array of numbers and BigInts!

``````const mixed = [4n, 6, -10n, 10, 4, 0, 0n]
mixed.sort() // default sorting behavior
// =>  [ -10n, 0, 0n, 10, 4n, 4, 6 ]
``````

But as you might see, this is not the type of sorting you were perhaps expecting. This is because the default sort does not compare the numbers by value. Instead, the the default sort order is ascending and based upon converting the elements into strings, then comparing their sequences of UTF-16 code values.

So the usual way to sort numbers by value is to provide a custom sort function, like this:

``````const mixed = [10, 2, -1, 0, 6];
mixed.sort((a, b) => a - b);
// => [ -1, 0, 2, 6, 10 ]
``````

But this won’t worked with our mixed array:

``````const mixed = [4n, 6, -10n, 10, 4, 0, 0n]
mixed.sort((a, b) => a - b);
// => Uncaught TypeError: can't convert BigInt to number
``````

### BigInt Operation

You can perform regular operations such as `+`, `-`, `*`, `**` and `%` between two BigInts, but you cannot mix them with regular numbers. If you’re dealing with BigInts, then cast every operand into a BigInt to ensure there is no loss of precision or runtime error.

## BigDecimal

Sadly, this type does not exist in JavaScript and you’ll have to look into userland solutions to find a library that fits your needs.

## Summary

I’d suggest using the option that fits the use case the best and thoroughly testing your data transformation code with unit tests. For me this is usually `parseInt` as integers are usually what I’m working with in my web apps. Even if what you need is decimal, you can think about repesenting it as an integer.

For, example `\$9.99` can be stored internally as `999` cents and formatted as `9.99` on the UI.

Be careful to account for the possibility of `NaN` or `Infinity` and handling such errors gracefully!