How can I convert a string like 123,456.908 to float 123456.908 in Python?
Asked
Active
Viewed 2.5e+01k times
121
codeforester
- 34,080
- 14
- 96
- 122
kevinlu
- 1,571
- 2
- 12
- 18
-
12The proper way to do this is to use the `locale` module - everything else is just a very nasty hack that will get you into trouble in the future. – Nick Bastin Jul 09 '11 at 09:30
-
1The proper `locale`way is also a very good way to shoot you in the foot if you plan to use your program on several operating systems (like Windows and flavors of Linux), which have different locale formats or even might need you to install a locale that supports your chosen format... – 576i Feb 23 '21 at 20:30
9 Answers
186
... Or instead of treating the commas as garbage to be filtered out, we could treat the overall string as a localized formatting of the float, and use the localization services:
from locale import atof, setlocale, LC_NUMERIC
setlocale(LC_NUMERIC, '') # set to your default locale; for me this is
# 'English_Canada.1252'. Or you could explicitly specify a locale in which floats
# are formatted the way that you describe, if that's not how your locale works :)
atof('123,456') # 123456.0
# To demonstrate, let's explicitly try a locale in which the comma is a
# decimal point:
setlocale(LC_NUMERIC, 'French_Canada.1252')
atof('123,456') # 123.456
Juta
- 361
- 3
- 12
Karl Knechtel
- 56,349
- 8
- 83
- 124
-
5
-
2I'd up-vote this answer if the examples included both a decimal point and digit grouping characters in them... – martineau Jul 09 '11 at 20:38
-
16Fine for a script, bad for a library: `Extension modules should never call setlocale()` – blueFast Apr 29 '14 at 14:10
-
atof() is deprecated since version 2.0. So I guess removing ',' from the string is the way to go. – umbersar Jan 19 '15 at 22:29
-
15@wanderer: what's deprecated is the `atof` *builtin method of strings*. What I'm using here is the function `atof` from the `locale` standard library module, which is not deprecated at all. – Karl Knechtel Aug 29 '15 at 01:03
-
6That's why star imports are bad - I would suggest you edit this to either import what's needed or better namespace as in `locale.atof` – Mr_and_Mrs_D Feb 20 '18 at 13:26
-
2This is good, but one thing to note, though, is that seemingly the thousand separator ("," in en_US, "." in de_DE) is completely ignored and a string like `"1,23,,.4,56"` is converted without error to `123.456` (in en_US). – Yushin Washio Feb 11 '19 at 12:55
-
1@Mr_and_Mrs_D there is no ambiguity, because I'm using a top-level function provided by the module, rather than a method. But I agree that it makes the code clearer to show the imports explicitly, i.e. to point out that both functions come from the module rather than builtin. So I've adjusted that. – Karl Knechtel Oct 11 '19 at 22:50
-
@YushinWashio Good to know. I guess you could defend this as an application of [Postel's Law](https://en.wikipedia.org/wiki/Robustness_principle), but the standard library is definitely stricter than that in some other places. I do know that different locales have different rules for where the commas ought to be, but it's not clear to me what other rule you could use for acceptance. Maybe "either commas in the exact places demanded by the locale, or none at all"? – Karl Knechtel Oct 11 '19 at 22:53
166
Just remove the , with replace():
float("123,456.908".replace(',',''))
zeekay
- 49,858
- 13
- 107
- 105
-
20this depends on locale. 9 988 776,65 € in France 9.988.776,65 € in Germany $9,988,776.65 in the United States – Alexandru R Dec 29 '16 at 19:58
-
If you are writing constants in the source code and want to use commas to make it more readable then this is the way to go rather than locale which would then make the code fail in another location. ```python cd_size = float("737,280,000".replace(',',''))``` (I actually used int) – hum3 Jun 01 '18 at 11:30
-
1If you are writing a string literal constant in the source code and then explicitly converting it to integer or float, that's a sign of something wrong with the design. But even if it can be defended - just temporarily set the locale to the one the code is written in, for that context, and then restore the context appropriate to your users when handling user input. That's why there is `setlocale` in the first place. – Karl Knechtel Oct 11 '19 at 22:56
-
1
-
This extremely dangerous replacement would [fail in half of the world](https://en.wikipedia.org/wiki/Decimal_separator#/media/File:DecimalSeparator.svg), the other half being China. And the US. Europe, Africa, Russia, South America, use `,` as the decimal separator – Panagiotis Kanavos Jan 14 '21 at 13:15
-
@hum3 PEP 515 introduced underscores for numeric literals. In Python 3.6 you can just write 737_280_000 instead of doing string manipulations to make things more readable. – Malcolm Jun 18 '21 at 04:18
-
Thank @Malcolm I think PEP-515 is a better solution if you have control over the text. In my case I didn't as was getting someone elses input. – hum3 Jun 20 '21 at 13:10
12
If you don't know the locale and you want to parse any kind of number, use this parseNumber(text) function. It is not perfect but take into account most cases :
>>> parseNumber("a 125,00 €")
125
>>> parseNumber("100.000,000")
100000
>>> parseNumber("100 000,000")
100000
>>> parseNumber("100,000,000")
100000000
>>> parseNumber("100 000 000")
100000000
>>> parseNumber("100.001 001")
100.001
>>> parseNumber("$.3")
0.3
>>> parseNumber(".003")
0.003
>>> parseNumber(".003 55")
0.003
>>> parseNumber("3 005")
3005
>>> parseNumber("1.190,00 €")
1190
>>> parseNumber("1190,00 €")
1190
>>> parseNumber("1,190.00 €")
1190
>>> parseNumber("$1190.00")
1190
>>> parseNumber("$1 190.99")
1190.99
>>> parseNumber("1 000 000.3")
1000000.3
>>> parseNumber("1 0002,1.2")
10002.1
>>> parseNumber("")
>>> parseNumber(None)
>>> parseNumber(1)
1
>>> parseNumber(1.1)
1.1
>>> parseNumber("rrr1,.2o")
1
>>> parseNumber("rrr ,.o")
>>> parseNumber("rrr1rrr")
1
hayj
- 911
- 11
- 20
9
If you have a comma as decimals separator and the dot as thousands separator, you can do:
s = s.replace('.','').replace(',','.')
number = float(s)
Hope it will help
Luca Di Liello
- 1,304
- 15
- 32
6
What about this?
my_string = "123,456.908"
commas_removed = my_string.replace(',', '') # remove comma separation
my_float = float(commas_removed) # turn from string to float.
In short:
my_float = float(my_string.replace(',', ''))
Aufwind
- 23,814
- 37
- 104
- 151
4
Better solution for different currency formats:
def text_currency_to_float(text):
t = text
dot_pos = t.rfind('.')
comma_pos = t.rfind(',')
if comma_pos > dot_pos:
t = t.replace(".", "")
t = t.replace(",", ".")
else:
t = t.replace(",", "")
return(float(t))
Quincy Hsieh
- 164
- 1
- 10
2
Here's a simple way I wrote up for you. :)
>>> number = '123,456,789.908'.replace(',', '') # '123456789.908'
>>> float(number)
123456789.908
John Doe
- 3,334
- 1
- 16
- 21
-
-
@John Doe: Looks way better now. I like `float(number)` because of its descriptive touch. +1 ;-) – Aufwind Jul 09 '11 at 08:21
-
29 988 776,65 € in France 9.988.776,65 € in Germany $9,988,776.65 in the United States ----> Are you sure it works? – Alexandru R Dec 29 '16 at 19:59
1
Just replace, with replace().
f = float("123,456.908".replace(',','')) print(type(f))
type() will show you that it has converted into a float
Vibhor Karnawat
- 90
- 1
- 12
-
1these are all good answers. As I do `df = pd.read_csv(filename, __thousands=','__) it solves the issue during read already for all potential columns. – Oliver Prislan Oct 04 '21 at 09:14