ฉันจะแยกสตริงเพื่อลอยหรือ int ได้อย่างไร


2251

ใน Python ฉันจะแยกสตริงที่เป็นตัวเลขเช่นเดียว"545.2222"กับค่าทศนิยมที่สอดคล้องกันได้545.2222อย่างไร? หรือแยกสตริง"31"เป็นจำนวนเต็ม31?

ผมแค่อยากจะรู้วิธีการแยกลอย strไปfloatและ (แยกต่างหาก) ความint ไปยังstrint


7
ตามกฎทั่วไปหากคุณมีวัตถุใน Python และต้องการแปลงเป็นวัตถุชนิดนั้นให้เรียกtype(my_object)ใช้ ผลที่ได้มักจะสามารถเรียกได้ว่าเป็นฟังก์ชั่นที่จะทำการแปลง ตัวอย่างเช่นtype(100)ผลลัพธ์เป็นintดังนั้นคุณสามารถโทรint(my_object)เพื่อลองแปลงmy_objectเป็นจำนวนเต็ม สิ่งนี้ไม่ได้ผลเสมอไป แต่เป็น "การคาดเดาครั้งแรก" ที่ดีเมื่อทำการเข้ารหัส
robertlayton

int(x) if int(x) == float(x) else float(x)
tcpaiva

คำตอบ:


2623
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545

8
แค่สงสัยว่าทำไมมี '04' ในที่สุด? ทำไมไม่ใช่แค่ '00' ไพ ธ อนรุ่นปัจจุบันของฉันก็ไม่มี '04'
Mangat Rai Modi

54
@ MangatRaiModi ตัวเลขจุดลอยตัวมีความไม่สมบูรณ์สำหรับการแทนทศนิยม สำหรับข้อมูลเพิ่มเติมโปรดดูstackoverflow.com/q/21895756/931277
dokkaebi

19
ทำไมไม่เพียงint(a)แต่int(float(a))?
idclev 463035818

24
int(a)จะให้ข้อผิดพลาดว่าสตริงไม่ใช่จำนวนเต็มที่ถูกต้อง: ValueError: invalid literal for int() with base 10: '545.222'แต่การแปลงจาก float เป็น int คือการแปลงที่รองรับ
David Parks

4
คุณควรจัดการValueErrorหากคุณต้องการความปลอดภัย
Joe Bobson

515
def num(s):
    try:
        return int(s)
    except ValueError:
        return float(s)

81
การผสมโดยปริยายลอย / ints อาจนำไปสู่ข้อบกพร่องที่ลึกซึ้งเนื่องจากการสูญเสียความแม่นยำที่เป็นไปได้เมื่อทำงานกับลอยหรือผลที่แตกต่างกันสำหรับ/ผู้ประกอบการในลอย / ints ขึ้นอยู่กับบริบทมันอาจจะดีกว่าที่จะคืนค่า int หรือ float ไม่ใช่ทั้งสองอย่าง
jfs

14
@JFSebastian คุณถูกต้องครบถ้วน แต่มีบางครั้งที่คุณต้องการให้อินพุตป้อนตามที่จะเป็น ปล่อยให้อินพุตกำหนดว่าตัวใดสามารถทำงานได้ดีกับการพิมพ์แบบเป็ด
TimothyAWiseman

4
คุณสามารถซ้อนอีกอันtryเพื่อโยนข้อยกเว้นเมื่อมันไม่สามารถลอยได้
iBug

2
ล้มเหลวด้วยs = u'\u0000'
Matt Hancock

1
@iBug ความคิดที่ดี! ฉันขอแนะนำให้โยนValueErrorในที่สอดคล้องexceptกัน: P
marcelm

511

วิธี Python เพื่อตรวจสอบว่าสตริงเป็นทศนิยมหรือไม่:

def is_float(value):
  try:
    float(value)
    return True
  except:
    return False

ชื่อที่ยาวและแม่นยำมากขึ้นสำหรับฟังก์ชันนี้อาจเป็น: is_convertible_to_float(value)

อะไรคือสิ่งที่ไม่ใช่โฟลทในPythonอาจทำให้คุณประหลาดใจ:

val                   is_float(val) Note
--------------------  ----------   --------------------------------
""                    False        Blank string
"127"                 True         Passed string
True                  True         Pure sweet Truth
"True"                False        Vile contemptible lie
False                 True         So false it becomes true
"123.456"             True         Decimal
"      -127    "      True         Spaces trimmed
"\t\n12\r\n"          True         whitespace ignored
"NaN"                 True         Not a number
"NaNanananaBATMAN"    False        I am Batman
"-iNF"                True         Negative infinity
"123.E4"              True         Exponential notation
".1"                  True         mantissa only
"1,234"               False        Commas gtfo
u'\x30'               True         Unicode is fine.
"NULL"                False        Null is not special
0x3fade               True         Hexadecimal
"6e7777777777777"     True         Shrunk to infinity
"1.797693e+308"       True         This is max value
"infinity"            True         Same as inf
"infinityandBEYOND"   False        Extra characters wreck it
"12.34.56"            False        Only one dot allowed
u'四'                 False        Japanese '4' is not a float.
"#56"                 False        Pound sign
"56%"                 False        Percent of what?
"0E0"                 True         Exponential, move dot 0 places
0**0                  True         0___0  Exponentiation
"-5e-5"               True         Raise to a negative number
"+1e1"                True         Plus is OK with exponent
"+1e1^5"              False        Fancy exponent not interpreted
"+1e1.3"              False        No decimals in exponent
"-+1"                 False        Make up your mind
"(1)"                 False        Parenthesis is bad

คุณคิดว่าคุณรู้ว่าตัวเลขคืออะไร? คุณไม่ค่อยดีอย่างที่คิด! ไม่แปลกใจเลย

อย่าใช้รหัสนี้กับซอฟต์แวร์ที่มีความสำคัญต่อชีวิต!

การจับข้อยกเว้นในวงกว้างด้วยวิธีนี้การฆ่านกขมิ้นและการกลืนกินข้อยกเว้นนั้นสร้างโอกาสเล็กน้อยที่การลอยตัวที่ถูกต้องตามสตริงจะคืนค่าเท็จ float(...)บรรทัดของรหัสสามารถล้มเหลวสำหรับการใด ๆ ของพันเหตุผลที่ไม่มีอะไรจะทำอย่างไรกับเนื้อหาของสตริง แต่ถ้าคุณกำลังเขียนซอฟต์แวร์ที่สำคัญต่อชีวิตในภาษาต้นแบบการพิมพ์เป็ดเช่น Python แสดงว่าคุณมีปัญหามากขึ้น


1
จริงกลายเป็น 1 นั่นคือฉันสืบทอดมาจาก C ++ ฉันคิดว่า
FindOutIslamNow

6
ฉันโพสต์คำตอบนี้ในปี 2014 UTF-8สัญลักษณ์สำหรับภาษาจีน4ได้รับการเปลี่ยนแปลงในช่วงหลายปีที่ผ่านมาขึ้นอยู่กับว่านักพัฒนา stackoverflow เปลี่ยนรูปแบบการเข้ารหัสตัวอักษรของพวกเขาบนไมโครซอฟท์สต็อกได้อย่างไร มันเป็นความอยากรู้อยากเห็นที่จะพลิกล้มเหลวในช่วงหลายปีที่ผ่านมาเป็นแผนการแปลงใหม่ยืนยันถึงอุดมการณ์ใหม่ของพวกเขา แต่ใช่UTF-8สัญลักษณ์ใด ๆสำหรับตัวเลขตะวันออกตะวันออกไม่ใช่ Python float Bazinga
Eric Leschinski

4
สิ่งนี้จะถูกยกระดับขึ้นได้อย่างไรด้วยข้อยกเว้นแบบกว้างเช่นนี้?
E.Serra

ทุกอย่างที่มีช่องว่างในระหว่างไม่สามารถแปลงได้เช่น"- 12.3"และ"45 e6"
Simon

1
นี้ยกเว้นข้อควรถูก จำกัด ให้TypeError, ValueError
Wim

131

นี่เป็นอีกวิธีหนึ่งที่สมควรได้รับการกล่าวถึงที่นี่ast.literal_eval :

สิ่งนี้สามารถใช้สำหรับการประเมินสตริงที่มีนิพจน์ Python อย่างปลอดภัยจากแหล่งข้อมูลที่ไม่น่าเชื่อถือโดยไม่จำเป็นต้องแยกวิเคราะห์ค่าของตัวเอง

นั่นคือความปลอดภัย 'eval'

>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31

11
นี่ไม่ใช่วิธีแก้ไขปัญหาที่ดี มันใช้งานได้ดีใน Python 2 แต่สิ่งต่อไปนี้เกิดขึ้นใน Python 3: python >>> import ast >>> ast.literal_eval('1-800-555-1212') -2566 >>> เพื่อชี้แจงสาเหตุที่เป็นปัญหาหากคุณต้องการให้หมายเลขโทรศัพท์เพียงอย่างเดียวและไม่คิดว่ามันเป็นนิพจน์ทางคณิตศาสตร์วิธีนี้ไม่เหมาะสำหรับคุณ
royce3

6
@ royce3 ใช่นั่นเป็นจุดที่ดีและผู้ใช้ควรระวัง แต่เดิมมีการปรับเปลี่ยนพฤติกรรมเพื่อแก้ไขปัญหาบางอย่างด้วยการวิเคราะห์ตัวอักษรที่ซับซ้อน มันเป็นเนื้อหาข้อผิดพลาดในast.literal_evalและได้รับการกล่าวถึงที่นี่
Wim

79
float(x) if '.' in x else int(x)

21
หมายเหตุ: โปรดระมัดระวังเมื่อจัดการกับจำนวนเงินที่ส่งผ่านเป็นสตริงเนื่องจากบางประเทศใช้ "," เป็นตัวคั่นทศนิยม
Ben G

127
@Emile: ฉันจะไม่เรียก "2e-3" เป็น "กรณีที่รุนแรง" คำตอบนี้ขาดไป
jchl

14
@BenG อย่าจัดการกับเงินในรูปแบบลอยตัว นั่นคือการขอปัญหา ใช้ทศนิยมเพื่อเงิน! (แต่ความคิดเห็นของคุณเกี่ยวกับ ',' ยังคงใช้ได้และสำคัญ)
ToolmakerSteve

4
อย่าลืมว่า "ไม่ใช่ตัวเลข" (NaN) และ +/- อินฟินิตี้เป็นค่าทศนิยมที่ถูกต้องเช่นกัน ดังนั้นfloat("nan")ค่าลอยที่ถูกต้องสมบูรณ์แบบที่คำตอบข้างต้นจะไม่สามารถจับได้เลย
Ronny Andersson

2
เปราะบางได้อย่างง่ายดายโดยที่อยู่ IP - 192.168.0.1; หรือ"This is not a good approach. :)"
Todor Minakov

69

รองรับหลายภาษาและจุลภาค

คุณควรพิจารณาความเป็นไปได้ของเครื่องหมายจุลภาคในการแสดงสตริงของตัวเลขสำหรับกรณี float("545,545.2222")ที่มีข้อผิดพลาดเกิดขึ้น ให้ใช้วิธีการในlocaleการแปลงสตริงเป็นตัวเลขและตีความเครื่องหมายจุลภาคอย่างถูกต้อง locale.atofวิธีการแปรรูปลอยในขั้นตอนเดียวครั้งเดียวที่เกิดเหตุได้รับการตั้งค่าสำหรับการประชุมจำนวนที่ต้องการ

ตัวอย่างที่ 1 - อนุสัญญาหมายเลขประเทศสหรัฐอเมริกา

ในสหรัฐอเมริกาและสหราชอาณาจักรเครื่องหมายจุลภาคสามารถใช้เป็นตัวคั่นหลักพันได้ ในตัวอย่างนี้ด้วยโลแคลอเมริกันเครื่องหมายจุลภาคถูกจัดการอย่างเหมาะสมเป็นตัวคั่น:

>>> import locale
>>> a = u'545,545.2222'
>>> locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
'en_US.UTF-8'
>>> locale.atof(a)
545545.2222
>>> int(locale.atof(a))
545545
>>>

ตัวอย่างที่ 2 - อนุสัญญาหมายเลขยุโรป

ในประเทศส่วนใหญ่ของโลกเครื่องหมายจุลภาคจะใช้สำหรับเครื่องหมายทศนิยมแทนจุด ในตัวอย่างนี้ด้วยโลแคลภาษาฝรั่งเศสเครื่องหมายจุลภาคถูกจัดการอย่างถูกต้องเป็นเครื่องหมายทศนิยม:

>>> import locale
>>> b = u'545,2222'
>>> locale.setlocale(locale.LC_ALL, 'fr_FR')
'fr_FR'
>>> locale.atof(b)
545.2222

วิธีlocale.atoiนี้ยังมีอยู่ แต่อาร์กิวเมนต์ควรเป็นจำนวนเต็ม


ดูเหมือนว่าจะเป็นทางออกที่ดีเมื่อคุณรู้ว่าควรส่งคืน float หรือ int แต่คุณจะได้รับวิธีนี้ส่งคืน int เฉพาะเมื่อผ่าน int หรือไม่ ตัวอย่างเช่นx = '1'; locale.atof(x)ผลตอบแทนเมื่อฉันต้องการจริง1.0 1
user5359531

ใช้วิธีการของ Dino ฉันเดาคำตอบว่าจะใช้สิ่งนี้:locale.atof(x) if locale.localeconv().get('decimal_point') in x else locale.atoi(x)
user5359531

ฉันอยากจะแนะนำให้ใช้วิธีของ Javier ด้านบน ( locale.atoiลองดูและใช้โดยการlocale.atofยกเว้น - มันน่าจะอ่านได้มากกว่า)
Mark Chackerian

27

หากคุณไม่ชอบโมดูลของบุคคลที่สามคุณสามารถตรวจสอบโมดูลfastnumbersได้ มันมีฟังก์ชั่นที่เรียกว่าfast_realซึ่งทำในสิ่งที่คำถามนี้ถามและทำได้เร็วกว่าการนำ Python ไปใช้จริง:

>>> from fastnumbers import fast_real
>>> fast_real("545.2222")
545.2222
>>> type(fast_real("545.2222"))
float
>>> fast_real("31")
31
>>> type(fast_real("31"))
int

24

ผู้ใช้codelogicและฮาร์เลย์ที่ถูกต้อง แต่เก็บไว้ในใจถ้าคุณรู้ว่าสตริงเป็นจำนวนเต็ม (เช่น 545) คุณสามารถเรียก int ( "545") โดยไม่ต้องหล่อคนแรกที่จะลอย

หากสตริงของคุณอยู่ในรายการคุณสามารถใช้ฟังก์ชันแผนที่ได้เช่นกัน

>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>

มันจะดีก็ต่อเมื่อพวกมันเป็นประเภทเดียวกันทั้งหมด


21

ใน Python ฉันจะแยกสตริงตัวเลขเช่น "545.2222" เป็นค่าทศนิยมที่สอดคล้องกันได้อย่างไร 542.2222 หรือแยกสตริง "31" เป็นจำนวนเต็ม 31? ฉันแค่อยากรู้วิธีแยกสตริงลอยเป็นลอยและ (แยก) สตริง int เป็น int

เป็นการดีที่คุณขอให้ทำสิ่งเหล่านี้แยกจากกัน หากคุณกำลังผสมพวกเขาคุณอาจตั้งค่าตัวเองสำหรับปัญหาในภายหลัง คำตอบง่ายๆคือ:

"545.2222" ลอย:

>>> float("545.2222")
545.2222

"31" เป็นจำนวนเต็ม:

>>> int("31")
31

การแปลงอื่น ๆ ints ไปและกลับจากสตริงและตัวอักษร:

การแปลงจากฐานต่าง ๆ และคุณควรทราบฐานล่วงหน้า (10 เป็นค่าเริ่มต้น) หมายเหตุคุณสามารถใส่คำนำหน้าด้วยสิ่งที่ Python คาดหวังสำหรับตัวอักษร (ดูด้านล่าง) หรือลบคำนำหน้า:

>>> int("0b11111", 2)
31
>>> int("11111", 2)
31
>>> int('0o37', 8)
31
>>> int('37', 8)
31
>>> int('0x1f', 16)
31
>>> int('1f', 16)
31

หากคุณไม่ทราบพื้นฐานล่วงหน้า แต่คุณรู้ว่ามันจะมีส่วนนำหน้าที่ถูกต้อง Python สามารถอนุมานสิ่งนี้ให้คุณได้ถ้าคุณผ่าน0เป็นฐาน:

>>> int("0b11111", 0)
31
>>> int('0o37', 0)
31
>>> int('0x1f', 0)
31

ตัวอักษรที่ไม่ใช่ทศนิยม (เช่นจำนวนเต็ม) จากฐานอื่น

หากแรงจูงใจของคุณคือการมีรหัสของคุณเองอย่างชัดเจนแสดงถึงค่าเฉพาะที่กำหนดค่าตายตัวคุณอาจไม่จำเป็นต้องแปลงจากฐาน - คุณสามารถปล่อยให้ Python ทำเพื่อคุณโดยอัตโนมัติพร้อมกับไวยากรณ์ที่ถูกต้อง

คุณสามารถใช้คำนำหน้าในเรื่องที่จะได้รับการแปลงโดยอัตโนมัติเพื่อจำนวนเต็มกับตัวอักษรต่อไปนี้ สิ่งเหล่านี้ใช้ได้กับ Python 2 และ 3:

ไบนารีคำนำหน้า 0b

>>> 0b11111
31

แปดคำนำหน้า 0o

>>> 0o37
31

เลขฐานสิบหกคำนำหน้า 0x

>>> 0x1f
31

สิ่งนี้มีประโยชน์เมื่ออธิบายแฟล็กไบนารีการอนุญาตไฟล์ในโค้ดหรือค่าฐานสิบหกสำหรับสี - ตัวอย่างเช่นไม่ต้องใส่เครื่องหมายคำพูด:

>>> 0b10101 # binary flags
21
>>> 0o755 # read, write, execute perms for owner, read & ex for group & others
493
>>> 0xffffff # the color, white, max values for red, green, and blue
16777215

การทำให้ Python 2 แบบไม่ชัดเจนนั้นเข้ากันได้กับ Python 3

หากคุณเห็นจำนวนเต็มที่เริ่มต้นด้วย 0 ใน Python 2 นี่คือไวยากรณ์ฐานแปด (คัดค้าน)

>>> 037
31

มันไม่ดีเพราะดูเหมือนว่าควรจะมี37ค่า ดังนั้นใน Python 3 ตอนนี้จะเพิ่มSyntaxError:

>>> 037
  File "<stdin>", line 1
    037
      ^
SyntaxError: invalid token

แปลง Python 2 octals เป็น octals ที่ใช้ได้ทั้ง 2 และ 3 ด้วย0oคำนำหน้า:

>>> 0o37
31

20

คำถามดูเหมือนจะเก่าไปหน่อย แต่ให้ฉันแนะนำฟังก์ชั่น parseStr ซึ่งทำให้คล้ายกันนั่นคือคืนค่าจำนวนเต็มหรือทศนิยมและหากสตริง ASCII ที่กำหนดไม่สามารถแปลงเป็นไม่มีพวกเขามันส่งคืนมันมิได้ถูกแตะต้อง รหัสของหลักสูตรอาจถูกปรับให้ทำในสิ่งที่คุณต้องการเท่านั้น:

   >>> import string
   >>> parseStr = lambda x: x.isalpha() and x or x.isdigit() and \
   ...                      int(x) or x.isalnum() and x or \
   ...                      len(set(string.punctuation).intersection(x)) == 1 and \
   ...                      x.count('.') == 1 and float(x) or x
   >>> parseStr('123')
   123
   >>> parseStr('123.3')
   123.3
   >>> parseStr('3HC1')
   '3HC1'
   >>> parseStr('12.e5')
   1200000.0
   >>> parseStr('12$5')
   '12$5'
   >>> parseStr('12.2.2')
   '12.2.2'

8
1e3เป็นตัวเลขในไพ ธ อน แต่เป็นสตริงตามโค้ดของคุณ
Cees Timmerman

16

float("545.2222") และ int(float("545.2222"))


1
สิ่งนี้จะทำให้คุณมีวัตถุลอยถ้าสตริงของคุณเป็น "0" หรือ "0.0" แทนที่จะเป็น int จะให้หมายเลขที่ถูกต้องอื่น ๆ
Brian

14

ฉันใช้ฟังก์ชั่นนี้เพื่อสิ่งนั้น

import ast

def parse_str(s):
   try:
      return ast.literal_eval(str(s))
   except:
      return

มันจะแปลงสตริงเป็นประเภทของมัน

value = parse_str('1')  # Returns Integer
value = parse_str('1.5')  # Returns Float

โปรดสังเกตว่าparse_str(' 1')(มีช่องว่าง) จะกลับมาไม่ได้None 1
musiphil

13

YAML parser สามารถช่วยคุณคิดออกว่าประเภทข้อมูลสายของคุณคือ ใช้yaml.load()จากนั้นคุณสามารถใช้type(result)ทดสอบประเภท:

>>> import yaml

>>> a = "545.2222"
>>> result = yaml.load(a)
>>> result
545.22220000000004
>>> type(result)
<type 'float'>

>>> b = "31"
>>> result = yaml.load(b)
>>> result
31
>>> type(result)
<type 'int'>

>>> c = "HI"
>>> result = yaml.load(c)
>>> result
'HI'
>>> type(result)
<type 'str'>

11
def get_int_or_float(v):
    number_as_float = float(v)
    number_as_int = int(number_as_float)
    return number_as_int if number_as_float == number_as_int else number_as_float

1
ทำไมคุณจะเพิ่มในexceptส่วนของคุณถ้าคุณไม่ทำอะไรที่นั่น? ลอย () จะเพิ่มสำหรับคุณ
Greg0ry

1
คุณพูดถูกฉันคัดลอกและวางจากฟังก์ชั่นที่ฉันเพิ่มข้อยกเว้น จะแก้ไข ขอบคุณ
Totoro

1
นี้จะพยายามที่จะแยกสตริงและกลับอย่างใดอย่างหนึ่งintหรือfloatขึ้นอยู่กับสิ่งสตริงหมาย มันอาจเพิ่มข้อยกเว้นในการแยกวิเคราะห์หรือ [มีพฤติกรรมที่ไม่คาดคิด] [1]
Kuzeko

9
def num(s):
    """num(s)
    num(3),num(3.7)-->3
    num('3')-->3, num('3.7')-->3.7
    num('3,700')-->ValueError
    num('3a'),num('a3'),-->ValueError
    num('3e4') --> 30000.0
    """
    try:
        return int(s)
    except ValueError:
        try:
            return float(s)
        except ValueError:
            raise ValueError('argument is not a string of number')

6

คุณต้องคำนึงถึงการปัดเศษเพื่อทำสิ่งนี้อย่างถูกต้อง

Ie int (5.1) => 5 int (5.6) => 5 - ผิดควรเป็น 6 ดังนั้นเราจึงทำ int (5.6 + 0.5) => 6

def convert(n):
    try:
        return int(n)
    except ValueError:
        return float(n + 0.5)

4
จุดดี. แม้ว่าจะเป็นสาเหตุของเงินเฟ้อดังนั้นPython 3และภาษาสมัยใหม่อื่น ๆ จึงใช้การปัดเศษของนายธนาคาร
Cees Timmerman

2
คำตอบนี้ไม่ถูกต้อง (ตามที่เขียนไว้เดิม) มัน muddles สองกรณีของและint floatและมันจะให้ข้อยกเว้นเมื่อnเป็นสตริงตามที่ต้องการ OP บางทีคุณอาจจะหมายถึงเมื่อintผลเป็นที่ต้องการroundควรจะทำหลังจากการแปลงไปลอย ถ้าฟังก์ชั่นควรส่งคืนค่า int คุณก็ไม่จำเป็นต้องใช้ส่วนยกเว้น - ส่วนของฟังก์ชั่นทั้งหมดสามารถเป็นint(round(float(input)))ได้ ถ้าฟังก์ชั่นควรคืนค่า int ถ้าเป็นไปได้มิฉะนั้นจะเป็นทศนิยมวิธีการแก้ปัญหาดั้งเดิมของ javier นั้นถูกต้อง!
ToolmakerSteve

5

ฉันประหลาดใจที่ไม่มีใครพูดถึง regex เพราะบางครั้งสตริงต้องเตรียมและทำให้เป็นมาตรฐานก่อนที่จะส่งไปยังหมายเลข

import re
def parseNumber(value, as_int=False):
    try:
        number = float(re.sub('[^.\-\d]', '', value))
        if as_int:
            return int(number + 0.5)
        else:
            return number
    except ValueError:
        return float('nan')  # or None if you wish

การใช้งาน:

parseNumber('13,345')
> 13345.0

parseNumber('- 123 000')
> -123000.0

parseNumber('99999\n')
> 99999.0

และโดยวิธีการบางอย่างเพื่อยืนยันว่าคุณมีหมายเลข:

import numbers
def is_number(value):
    return isinstance(value, numbers.Number)
    # will work with int, float, long, Decimal

5

หากต้องการ typecast ใน python ให้ใช้ตัวสร้าง funtions ของประเภทนั้นส่งผ่านสตริง (หรือค่าใด ๆ ที่คุณพยายามแคสต์) เป็นพารามิเตอร์

ตัวอย่างเช่น:

>>>float("23.333")
   23.333

ไพ ธ อนกำลังเรียก__float__เมธอดobject ซึ่งควรคืนค่าการแสดงแบบลอยของพารามิเตอร์ สิ่งนี้มีประสิทธิภาพเป็นพิเศษเนื่องจากคุณสามารถกำหนดประเภทของคุณเอง (โดยใช้คลาส) ด้วย__float__วิธีการเพื่อให้มันสามารถส่งไปยังโฟลตโดยใช้โฟลว์ (myobject)


3

นี้เป็นรุ่นที่ได้รับการแก้ไขของ https://stackoverflow.com/a/33017514/5973334

นี้จะพยายามที่จะแยกสตริงและกลับอย่างใดอย่างหนึ่งintหรือfloatขึ้นอยู่กับสิ่งสตริงหมาย มันอาจจะเพิ่มขึ้นยกเว้นแยกหรือมีพฤติกรรมที่ไม่คาดคิด

  def get_int_or_float(v):
        number_as_float = float(v)
        number_as_int = int(number_as_float)
        return number_as_int if number_as_float == number_as_int else 
        number_as_float

2

ส่งผ่านสตริงของคุณไปยังฟังก์ชันนี้:

def string_to_number(str):
  if("." in str):
    try:
      res = float(str)
    except:
      res = str  
  elif(str.isdigit()):
    res = int(str)
  else:
    res = str
  return(res)

มันจะคืนค่า int, float หรือ string ขึ้นอยู่กับสิ่งที่ผ่าน

สตริงที่เป็น int

print(type(string_to_number("124")))
<class 'int'>

สตริงที่เป็นแบบลอย

print(type(string_to_number("12.4")))
<class 'float'>

สตริงที่เป็นสตริง

print(type(string_to_number("hello")))
<class 'str'>

สตริงที่ดูเหมือนลอย

print(type(string_to_number("hel.lo")))
<class 'str'>

1

ใช้:

def num(s):
    try:
        for each in s:
            yield int(each)
    except ValueError:
        yield float(each)
a = num(["123.55","345","44"])
print a.next()
print a.next()

นี่เป็นวิธีที่ Pythonic ที่สุดที่ฉันสามารถทำได้


floatเครื่องกำเนิดไฟฟ้าหยุดหลังจากการตีความแรกของ try... catchบล็อกอาจจะภายในforวง
musiphil

1

จัดการ hex, octal, binary, ทศนิยมและลอย

วิธีนี้จะจัดการกับอนุสัญญาสตริงทั้งหมดสำหรับตัวเลข (ทั้งหมดที่ฉันรู้)

def to_number(n):
    ''' Convert any number representation to a number 
    This covers: float, decimal, hex, and octal numbers.
    '''

    try:
        return int(str(n), 0)
    except:
        try:
            # python 3 doesn't accept "010" as a valid octal.  You must use the
            # '0o' prefix
            return int('0o' + n, 0)
        except:
            return float(n)

เอาต์พุตกรณีทดสอบนี้แสดงสิ่งที่ฉันกำลังพูดถึง

======================== CAPTURED OUTPUT =========================
to_number(3735928559)   = 3735928559 == 3735928559
to_number("0xFEEDFACE") = 4277009102 == 4277009102
to_number("0x0")        =          0 ==          0
to_number(100)          =        100 ==        100
to_number("42")         =         42 ==         42
to_number(8)            =          8 ==          8
to_number("0o20")       =         16 ==         16
to_number("020")        =         16 ==         16
to_number(3.14)         =       3.14 ==       3.14
to_number("2.72")       =       2.72 ==       2.72
to_number("1e3")        =     1000.0 ==       1000
to_number(0.001)        =      0.001 ==      0.001
to_number("0xA")        =         10 ==         10
to_number("012")        =         10 ==         10
to_number("0o12")       =         10 ==         10
to_number("0b01010")    =         10 ==         10
to_number("10")         =         10 ==         10
to_number("10.0")       =       10.0 ==         10
to_number("1e1")        =       10.0 ==         10

นี่คือการทดสอบ:

class test_to_number(unittest.TestCase):

    def test_hex(self):
        # All of the following should be converted to an integer
        #
        values = [

                 #          HEX
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (0xDEADBEEF  , 3735928559), # Hex
                ("0xFEEDFACE", 4277009102), # Hex
                ("0x0"       ,          0), # Hex

                 #        Decimals
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (100         ,        100), # Decimal
                ("42"        ,         42), # Decimal
            ]



        values += [
                 #        Octals
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (0o10        ,          8), # Octal
                ("0o20"      ,         16), # Octal
                ("020"       ,         16), # Octal
            ]


        values += [
                 #        Floats
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                (3.14        ,       3.14), # Float
                ("2.72"      ,       2.72), # Float
                ("1e3"       ,       1000), # Float
                (1e-3        ,      0.001), # Float
            ]

        values += [
                 #        All ints
                 # ----------------------
                 # Input     |   Expected
                 # ----------------------
                ("0xA"       ,         10), 
                ("012"       ,         10), 
                ("0o12"      ,         10), 
                ("0b01010"   ,         10), 
                ("10"        ,         10), 
                ("10.0"      ,         10), 
                ("1e1"       ,         10), 
            ]

        for _input, expected in values:
            value = to_number(_input)

            if isinstance(_input, str):
                cmd = 'to_number("{}")'.format(_input)
            else:
                cmd = 'to_number({})'.format(_input)

            print("{:23} = {:10} == {:10}".format(cmd, value, expected))
            self.assertEqual(value, expected)


0

นี้เป็นฟังก์ชั่นซึ่งจะแปลงใด ๆobject(ไม่เพียงstr) ไปintหรือfloatอยู่บนพื้นฐานถ้าสตริงที่เกิดขึ้นจริงที่จัดรูปลักษณ์ที่เหมือน หรือint floatนอกจากนี้หากเป็นวัตถุที่มีทั้งสอง__floatและ__int__วิธีการมันเริ่มต้นที่จะใช้__float__

def conv_to_num(x, num_type='asis'):
    '''Converts an object to a number if possible.
    num_type: int, float, 'asis'
    Defaults to floating point in case of ambiguity.
    '''
    import numbers

    is_num, is_str, is_other = [False]*3

    if isinstance(x, numbers.Number):
        is_num = True
    elif isinstance(x, str):
        is_str = True

    is_other = not any([is_num, is_str])

    if is_num:
        res = x
    elif is_str:
        is_float, is_int, is_char = [False]*3
        try:
            res = float(x)
            if '.' in x:
                is_float = True
            else:
                is_int = True
        except ValueError:
            res = x
            is_char = True

    else:
        if num_type == 'asis':
            funcs = [int, float]
        else:
            funcs = [num_type]

        for func in funcs:
            try:
                res = func(x)
                break
            except TypeError:
                continue
        else:
            res = x

-1

โดยใช้วิธีการ int และลอยเราสามารถแปลงสตริงเป็นจำนวนเต็มและลอย

s="45.8"
print(float(s))

y='67'
print(int(y))

คำตอบนี้ไม่ได้เพิ่มอะไรใหม่ ตัวอย่างเช่นดูคำตอบที่ให้ข้อมูลเดียวกันและอื่น ๆ
Georgy

-3

eval()เป็นทางออกที่ดีมากสำหรับคำถามนี้ ไม่จำเป็นต้องตรวจสอบว่าตัวเลขเป็น int หรือลอยมันก็ให้เทียบเท่าที่สอดคล้องกัน หากจำเป็นต้องใช้วิธีอื่นลอง

if '.' in string:
    print(float(string))
else:
    print(int(string))

ลองยกเว้นสามารถใช้เป็นทางเลือก ลองแปลงสตริงเป็น int ภายในบล็อคลอง หากสตริงจะเป็นค่าลอยมันจะโยนข้อผิดพลาดซึ่งจะถูกจับในบล็อกยกเว้นเช่นนี้

try:
    print(int(string))
except:
    print(float(string))

-10

นี่คืออีกการตีความคำถามของคุณ (คำใบ้: มันคลุมเครือ) เป็นไปได้ว่าคุณกำลังมองหาสิ่งนี้:

def parseIntOrFloat( aString ):
    return eval( aString )

มันใช้งานได้เช่นนี้ ...

>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545

ในทางทฤษฎีมีช่องโหว่การฉีด "import os; os.abort()"สตริงอาจยกตัวอย่างเช่นจะเป็น อย่างไรก็ตามไม่มีพื้นหลังใด ๆ ที่มาจากสตริงความเป็นไปได้คือการเก็งกำไรทางทฤษฎี เนื่องจากคำถามที่คลุมเครือนั้นไม่ชัดเจนเลยว่าช่องโหว่นี้มีอยู่จริงหรือไม่


7
แม้ว่าการป้อนข้อมูลของเขาเป็น 100% ปลอดภัย, eval()มีมากกว่า 3 try: int(s) except: float(s)ครั้งเป็นช้าเป็น
Cees Timmerman

1
ดีevalคือการปฏิบัติที่ดี (คุณต้องรู้เพราะคุณมีชื่อเสียง 310K)
U10 ไปข้างหน้า
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.