How to round a number to significant figures in Python - Stack ...
文章推薦指數: 80 %
You can use negative numbers to round integers: >>> round(1234, -3) 1000.0. Thus if you need only most significant digit:
Home
Public
Questions
Tags
Users
Collectives
ExploreCollectives
FindaJob
Jobs
Companies
Teams
StackOverflowforTeams
–Collaborateandshareknowledgewithaprivategroup.
CreateafreeTeam
WhatisTeams?
Teams
CreatefreeTeam
CollectivesonStackOverflow
Findcentralized,trustedcontentandcollaboratearoundthetechnologiesyouusemost.
Learnmore
Teams
Q&Aforwork
Connectandshareknowledgewithinasinglelocationthatisstructuredandeasytosearch.
Learnmore
HowtoroundanumbertosignificantfiguresinPython
AskQuestion
Asked
11years,4monthsago
Active
5daysago
Viewed
263ktimes
182
45
IneedtoroundafloattobedisplayedinaUI.e.g,toonesignificantfigure:
1234->1000
0.12->0.1
0.012->0.01
0.062->0.06
6253->6000
1999->2000
IsthereanicewaytodothisusingthePythonlibrary,ordoIhavetowriteitmyself?
pythonmathroundingsignificant-digits
Share
Follow
editedAug14at2:18
smci
28.2k1717goldbadges106106silverbadges142142bronzebadges
askedAug5'10at0:48
PeterGrahamPeterGraham
10.5k77goldbadges3636silverbadges4141bronzebadges
4
2
Areyoujustformattingtheoutput?Areyouaskingaboutthis?docs.python.org/library/stdtypes.html#string-formattingorthis?docs.python.org/library/string.html#string-formatting
– S.Lott
Aug5'10at0:53
whatoutputdoyouexpectfor0.062and6253?
– lamirap
Aug5'10at0:58
Thepackageto-precisionnowdoesthis.Mypostedanswerdetailshowthisapplies.
– WilliamRusnack
May23'17at12:13
1
Theanswerby@Falkengivestherequestedresults,whicharecorrect.Nearlyalltheothersgiveresultslike1000.0withtrailingdecimalpointsand/orzeros,whichinstandardpracticeindicatefarmoreprecision.
– nealmcb
Sep10'20at16:42
Addacomment
|
23Answers
23
Active
Oldest
Votes
167
Youcanusenegativenumberstoroundintegers:
>>>round(1234,-3)
1000.0
Thusifyouneedonlymostsignificantdigit:
>>>frommathimportlog10,floor
>>>defround_to_1(x):
...returnround(x,-int(floor(log10(abs(x)))))
...
>>>round_to_1(0.0232)
0.02
>>>round_to_1(1234243)
1000000.0
>>>round_to_1(13)
10.0
>>>round_to_1(4)
4.0
>>>round_to_1(19)
20.0
You'llprobablyhavetotakecareofturningfloattointegerifit'sbiggerthan1.
Share
Follow
editedJan7'16at6:43
TobiasKienzler
22.7k2121goldbadges115115silverbadges210210bronzebadges
answeredAug5'10at2:57
EvgenyEvgeny
2,63522goldbadges1616silverbadges1818bronzebadges
13
3
Thisisthecorrectsolution.Usinglog10istheonlyproperwaytodeterminehowtoroundit.
– Wolph
Aug5'10at3:23
85
round_to_n=lambdax,n:round(x,-int(floor(log10(x)))+(n-1))
– RoyHyunjinHan
Apr30'13at19:30
31
Youshoulduselog10(abs(x)),otherwisenegativenumberswillfail(Andtreatx==0separatelyofcourse)
– TobiasKienzler
Jul30'13at8:06
2
Ihavecreatedapackagethatdoesthisnowandisprobablyeasierandmorerobustthanthisone.PostLink,RepoLink.Hopethishelps!
– WilliamRusnack
May23'17at12:09
5
round_to_n=lambdax,n:xifx==0elseround(x,-int(math.floor(math.log10(abs(x))))+(n-1))protectsagainstx==0andx<0Thankyou@[email protected]'tprotectedagainstundefinedlikemath.inf,orgarbagelikeNoneetc
– AJP
Nov28'19at8:52
|
Show8morecomments
118
%ginstringformattingwillformatafloatroundedtosomenumberofsignificantfigures.Itwillsometimesuse'e'scientificnotation,soconverttheroundedstringbacktoafloatthenthrough%sstringformatting.
>>>'%s'%float('%.1g'%1234)
'1000'
>>>'%s'%float('%.1g'%0.12)
'0.1'
>>>'%s'%float('%.1g'%0.012)
'0.01'
>>>'%s'%float('%.1g'%0.062)
'0.06'
>>>'%s'%float('%.1g'%6253)
'6000.0'
>>>'%s'%float('%.1g'%1999)
'2000.0'
Share
Follow
answeredAug5'10at4:24
PeterGrahamPeterGraham
10.5k77goldbadges3636silverbadges4141bronzebadges
9
9
TheOP'srequirementwasfor1999tobeformattedas'2000',notas'2000.0'.Ican'tseeatrivialwaytochangeyourmethodtoachievethis.
– TimMartin
Jan14'11at16:04
1
It'sjustwhatIalwayswanted!where'dyoufindthis?
– djhaskin987
Jul19'13at20:34
14
Notethatthebehaviourof%gisnotalwayscorrect.Inparticularitalwaystrimstrailingzeroseveniftheyaresignificant.Thenumber1.23400has6significantdigits,but"%.6g"%(1.23400)willresultin"1.234"whichisincorrect.Moredetailsinthisblogpost:randlet.com/blog/python-significant-figures-format
– randlet
Oct29'13at17:49
3
JustlikethemethodinEvgeny'sanswer,thisfailstocorrectlyround0.075to0.08.Itreturns0.07instead.
– Gabriel
Mar8'16at23:02
2
round_sig=lambdaf,p:float(('%.'+str(p)+'e')%f)allowsyoutoadjustthenumberofsignificantdigits!
– denizb
Aug6'17at22:43
|
Show4morecomments
63
Ifyouwanttohaveotherthan1significantdecimal(otherwisethesameasEvgeny):
>>>frommathimportlog10,floor
>>>defround_sig(x,sig=2):
...returnround(x,sig-int(floor(log10(abs(x))))-1)
...
>>>round_sig(0.0232)
0.023
>>>round_sig(0.0232,1)
0.02
>>>round_sig(1234243,3)
1230000.0
Share
Follow
editedMar17'17at16:01
StephenRauch♦
42.9k3030goldbadges9292silverbadges115115bronzebadges
answeredAug5'10at9:49
indgarindgar
63144silverbadges22bronzebadges
8
8
round_sig(-0.0232)->mathdomainerror,youmaywanttoaddanabs()inthere;)
– dgorissen
Dec19'11at14:18
2
JustlikethemethodsinEvgeny'sandPeterGraham'sanswers,thisfailstocorrectlyround0.075to0.08.Itreturns0.07instead.
– Gabriel
Mar8'16at23:05
4
Alsoitfailsforround_sig(0).
– YuvalAtzmon
Feb21'17at11:36
2
@GabrielThatisabuiltin"feature"ofpythonrunningonyourcomputer,andmanifestitselfinitsbehaviorofthefunctionround.docs.python.org/2/tutorial/floatingpoint.html#tut-fp-issues
– NoviceC
May26'17at15:54
2
@GabrielI'veaddedananswerthatexplainswhyyoushouldexpecttoget0.7backfromrounding"0.075"!seestackoverflow.com/a/56974893/1358308
– SamMason
Jul10'19at16:22
|
Show3morecomments
52
f'{float(f"{i:.1g}"):g}'
#OrwithPython<3.6,
'{:g}'.format(float('{:.1g}'.format(i)))
Thissolutionisdifferentfromalloftheothersbecause:
itexactlysolvestheOPquestion
itdoesnotneedanyextrapackage
itdoesnotneedanyuser-definedauxiliaryfunctionormathematicaloperation
Foranarbitrarynumbernofsignificantfigures,youcanuse:
print('{:g}'.format(float('{:.{p}g}'.format(i,p=n))))
Test:
a=[1234,0.12,0.012,0.062,6253,1999,-3.14,0.,-48.01,0.75]
b=['{:g}'.format(float('{:.1g}'.format(i)))foriina]
#b==['1000','0.1','0.01','0.06','6000','2000','-3','0','-50','0.8']
Note:withthissolution,itisnotpossibletoadaptthenumberofsignificantfiguresdynamicallyfromtheinputbecausethereisnostandardwaytodistinguishnumberswithdifferentnumbersoftrailingzeros(3.14==3.1400).Ifyouneedtodoso,thennon-standardfunctionsliketheonesprovidedintheto-precisionpackageareneeded.
Share
Follow
editedApr16'20at14:41
AndyJones
4,18622goldbadges1616silverbadges1919bronzebadges
answeredFeb15'18at17:10
FalkenFalken
64955silverbadges88bronzebadges
9
1
FYI:IfoundthissolutionindependentlyfromeddygeekwhileIwastryingtosolvetheverysameprobleminoneofmycode.NowIrealizethatmysolutionis,obviously,almostidenticaltohis(Ijustnoticedtheerroneousoutputanddidn'tbothertoreadthecode,mymistake).Probablyashortcommentbeneathhisanswerwouldhavebeenenoughinsteadofanewanswer...Theonly(key)differenceisthedoubleuseofthe:gformatterwhichpreserveintegers.
– Falken
Feb15'18at17:32
3
Wow,youranswerneedstobereallyreadfromtoptobottom;)Thisdouble-casttrickisdirty,butneat.(Notethat1999formattedas2000.0suggests5significantdigits,soithastogothrough{:g}again.)Ingeneral,integerswithtrailingzerosareambiguouswithregardtosignificantfigures,unlesssometechnique(likeoverlineabovelastsignificant)isused.
– TomaszGandor
Apr6'20at6:45
1
Doyoumindtojustwalkmethroughhowthisworks?Whatare:.1gand:gIdontthinkivecomeacrosseitherbefore,andhaventfoundanythinginthedocseither
– E-A
Oct12'20at9:40
3
Forsomereason,thissolutionfailsforlongerprecisions.'{:g}'.format(float('{:.{p}g}'.format(0.123456789012,p=20)))resultsin0.123457.
– TomSwirly
Apr8at9:42
2
@TomSwirlyThereasonwhyyouaregettingamaximumprecisionof6isforthefirst'{:g}'(basedonthedocumentation:"Withnoprecisiongiven,usesaprecisionof6significantdigits").Ifyoupasstheprecisioninthat'{:g}'too,youwillgetthecorrectresult.Thecodewouldbe:'{:.{p}g}'.format(float('{:.{p}g}'.format(0.123456789012,p=12)),p=12)resultingin0.123456789012
– lscena
Jul27at20:37
|
Show4morecomments
11
Ihavecreatedthepackageto-precisionthatdoeswhatyouwant.Itallowsyoutogiveyournumbersmoreorlesssignificantfigures.
Italsooutputsstandard,scientific,andengineeringnotationwithaspecifiednumberofsignificantfigures.
Intheacceptedanswerthereistheline
>>>round_to_1(1234243)
1000000.0
Thatactuallyspecifies8sigfigs.Forthenumber1234243mylibraryonlydisplaysonesignificantfigure:
>>>fromto_precisionimportto_precision
>>>to_precision(1234243,1,'std')
'1000000'
>>>to_precision(1234243,1,'sci')
'1e6'
>>>to_precision(1234243,1,'eng')
'1e6'
Itwillalsoroundthelastsignificantfigureandcanautomaticallychoosewhatnotationtouseifanotationisn'tspecified:
>>>to_precision(599,2)
'600'
>>>to_precision(1164,2)
'1.2e3'
Share
Follow
editedJul29'18at23:45
offby1
5,9422727silverbadges4444bronzebadges
answeredMay23'17at11:59
WilliamRusnackWilliamRusnack
75877silverbadges1313bronzebadges
7
NowI'mlookingforthesamebutappliedtoapandasdf
– mhoff
Jan25'19at11:29
@mhoffyoucanprobablyusepandasmapwithalambda.lambdax:to_precision(x,2)
– WilliamRusnack
Feb7'19at19:44
Addthisto(PyPI)[pypi.org/].Thereisnothinglikethisthatexistsonthere,asfarasIcantell.
– Morgoth
Jul29'19at11:55
thisisagreatpackagebutIthinkmostofthefeaturesarenowinthesigfigmodule
– HyperActive
Nov30'19at17:32
2
ithasabug:std_notation(9.999999999999999e-05,3)gives:'0.00010'whichisonly2significantdigits
– BorisMulder
Mar31'20at11:58
|
Show2morecomments
11
Todirectlyanswerthequestion,here'smyversionusingnamingfromtheRfunction:
importmath
defsignif(x,digits=6):
ifx==0ornotmath.isfinite(x):
returnx
digits-=math.ceil(math.log10(abs(x)))
returnround(x,digits)
Mymainreasonforpostingthisanswerarethecommentscomplainingthat"0.075"roundsto0.07ratherthan0.08.Thisisdue,aspointedoutby"NoviceC",toacombinationoffloatingpointarithmetichavingbothfiniteprecisionandabase-2representation.Thenearestnumberto0.075thatcanactuallyberepresentedisslightlysmaller,henceroundingcomesoutdifferentlythanyoumightnaivelyexpect.
Alsonotethatthisappliestoanyuseofnon-decimalfloatingpointarithmetic,e.g.CandJavabothhavethesameissue.
Toshowinmoredetail,weaskPythontoformatthenumberin"hex"format:
0.075.hex()
whichgivesus:0x1.3333333333333p-4.Thereasonfordoingthisisthatthenormaldecimalrepresentationofteninvolvesroundingandhenceisnothowthecomputeractually"sees"thenumber.Ifyou'renotusedtothisformat,acoupleofusefulreferencesarethePythondocsandtheCstandard.
Toshowhowthesenumbersworkabit,wecangetbacktoourstartingpointbydoing:
0x13333333333333/16**13*2**-4
whichshouldshouldprintout0.075.16**13isbecausethereare13hexadecimaldigitsafterthedecimalpoint,and2**-4isbecausehexexponentsarebase-2.
Nowwehavesomeideaofhowfloatsarerepresentedwecanusethedecimalmoduletogiveussomemoreprecision,showinguswhat'sgoingon:
fromdecimalimportDecimal
Decimal(0x13333333333333)/16**13/2**4
giving:0.07499999999999999722444243844andhopefullyexplainingwhyround(0.075,2)evaluatesto0.07
Share
Follow
editedJul10'19at16:37
answeredJul10'19at16:21
SamMasonSamMason
12.2k11goldbadge3232silverbadges4646bronzebadges
6
3
Thisisagreatexplanationofwhy0.075isroundeddownto0.07atthecodelevel,butwe(inthephysicalsciences)havebeentaughttoalwaysroundupnotdown.Sotheexpectedbehaviourisactuallytohave0.08asaresult,floatingpointprecisionissuesnotwithstanding.
– Gabriel
Jul10'19at18:25
1
I'munsurewhereyourconfusionis:whenyouenter0.075you'reactuallyentering~0.07499(asabove),whichroundsaccordingtonormalmathsrules.ifyouwereusingadatatype(likedecimalfloatingpoint)thatcouldrepresent0.075thenitshouldindeedroundto0.08
– SamMason
Jul10'19at20:12
2
I'mnotconfused.WhenIenter0.075I'mactuallyentering0.075.WhateverhappensinthefloatingpointmathinsidethecodeIdon'tcare.
– Gabriel
Jul10'19at20:49
@Gabriel:Andifyouhaddeliberatelyentered0.074999999999999999,whatwouldyouexpecttogetinthatcase?
– MarkDickinson
Jul11'19at17:06
1
@MarkDickinsonthatdepends.Onesignificantfigure:0.07,two:0.075.
– Gabriel
Jul11'19at18:43
|
Show1morecomment
5
Toroundanintegerto1significantfigurethebasicideaistoconvertittoafloatingpointwith1digitbeforethepointandroundthat,thenconvertitbacktoitsoriginalintegersize.
Todothisweneedtoknowthelargestpowerof10lessthantheinteger.Wecanusefloorofthelog10functionforthis.
frommathimportlog10,floor
defround_int(i,places):
ifi==0:
return0
isign=i/abs(i)
i=abs(i)
ifi<1:
return0
max10exp=floor(log10(i))
ifmax10exp+1
延伸文章資訊
- 1Significant Figures Calculator and Counter
Add, subtract, multiply and divide significant figures, with step-by-step explanation and signifi...
- 2Brush up your maths: Significant figures
We round a number to three significant figures in the same way that we would round to three decim...
- 3Significant Figures - Montgomery College
All non-zero digits are always significant. 1.54 (3 sig. figs.) 45 (2 sig. figs.) 2. Interior zer...
- 4Rounding and estimating - KS3 Maths Revision - BBC Bitesize
Q1. Round 0.0724591 to 3 significant figures (s.f.).
- 5Rounding Significant Figures Calculator
Round a number to significant figures. ... Rules for rounding numbers to sig figs. ... Example in...