How to round a number to significant figures in Python - Stack ...

文章推薦指數: 80 %
投票人數:10人

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>>round(1.2322,2) 1.23 Integersaretrickier.They'renotstoredasbase10inmemory,sosignificantplacesisn'tanaturalthingtodo.It'sfairlytrivialtoimplementoncethey'reastringthough. Orforintegers: >>>defintround(n,sigfigs): ...n=str(n) ...returnn[:sigfigs]+('0'*(len(n)-(sigfigs))) >>>intround(1234,1) '1000' >>>intround(1234,2) Ifyouwouldliketocreateafunctionthathandlesanynumber,mypreferencewouldbetoconvertthembothtostringsandlookforadecimalplacetodecidewhattodo: >>>defroundall1(n,sigfigs): ...n=str(n) ...try: ...sigfigs=n.index('.') ...exceptValueError: ...pass ...returnintround(n,sigfigs) Anotheroptionistocheckfortype.Thiswillbefarlessflexible,andwillprobablynotplaynicelywithothernumberssuchasDecimalobjects: >>>defroundall2(n,sigfigs): ...iftype(n)isint:returnintround(n,sigfigs) ...else:returnround(n,sigfigs) Share Follow editedAug5'10at2:28 answeredAug5'10at1:35 TimMcNamaraTimMcNamara 17.2k33goldbadges5050silverbadges7878bronzebadges 2 Justmessingwithstringswon'troundthenumbers.1999roundedto1significantfigureis2000,not1000. – PeterGraham Aug5'10at2:43 ThereisagooddiscussionofthisproblemarchivedatActiveStatecode.activestate.com/lists/python-tutor/70739 – TimMcNamara Aug5'10at2:54 Addacomment  |  3 Ifyouwanttoroundwithoutinvolvingstrings,thelinkIfoundburiedinthecommentsabove: http://code.activestate.com/lists/python-tutor/70739/ strikesmeasbest.Thenwhenyouprintwithanystringformattingdescriptors,yougetareasonableoutput,andyoucanusethenumericrepresentationforothercalculationpurposes. Thecodeatthelinkisathreeliner:def,doc,andreturn.Ithasabug:youneedtocheckforexplodinglogarithms.Thatiseasy.Comparetheinputtosys.float_info.min.Thecompletesolutionis: importsys,math deftidy(x,n): """Return'x'roundedto'n'significantdigits.""" y=abs(x) ify<=sys.float_info.min:return0.0 returnround(x,int(n-math.ceil(math.log10(y)))) Itworksforanyscalarnumericvalue,andncanbeafloatifyouneedtoshifttheresponseforsomereason.Youcanactuallypushthelimitto: sys.float_info.min*sys.float_info.epsilon withoutprovokinganerror,ifforsomereasonyouareworkingwithminisculevalues. Share Follow answeredApr13'18at6:49 getting_sleepygetting_sleepy 3111bronzebadge Addacomment  |  3 Thepostedanswerwasthebestavailablewhengiven,butithasanumberoflimitationsanddoesnotproducetechnicallycorrectsignificantfigures. numpy.format_float_positionalsupportsthedesiredbehaviourdirectly.Thefollowingfragmentreturnsthefloatxformattedto4significantfigures,withscientificnotationsuppressed. importnumpyasnp x=12345.6 np.format_float_positional(x,precision=4,unique=False,fractional=False,trim='k') >12340. Share Follow answeredOct21'19at17:01 AutumnAutumn 2,1581515silverbadges3030bronzebadges 1 Thedocumentation(movedtonumpy.org/doc/stable/reference/generated/…)statesthatthisfunctionimplementstheDragon4algorithm(ofSteele&White1990,dl.acm.org/doi/pdf/10.1145/93542.93559).Itproducesannoyingresults,e.g.print(*[''.join([np.format_float_positional(.01*a*n,precision=2,unique=False,fractional=False,trim='k',pad_right=5)forain[.99,.999,1.001]])fornin[8,9,10,11,12,19,20,21]],sep='\n').Ididn'tcheckDragon4itself. – Rainald62 May12'20at15:09 Addacomment  |  2 Thesigfigpackage/librarycoversthis.Afterinstallingyoucandothefollowing: >>>fromsigfigimportround >>>round(1234,1) 1000 >>>round(0.12,1) 0.1 >>>round(0.012,1) 0.01 >>>round(0.062,1) 0.06 >>>round(6253,1) 6000 >>>round(1999,1) 2000 Share Follow answeredNov30'19at17:32 HyperActiveHyperActive 70877silverbadges1111bronzebadges Addacomment  |  1 Usingpython2.6+new-styleformatting(as%-styleisdeprecated): >>>"{0}".format(float("{0:.1g}".format(1216))) '1000.0' >>>"{0}".format(float("{0:.1g}".format(0.00356))) '0.004' Inpython2.7+youcanomittheleading0s. Share Follow answeredJan8'18at13:34 eddygeekeddygeek 3,58622goldbadges2121silverbadges2929bronzebadges 2 Withwhatversionofpython?Python3.6.3|Anaconda,Inc.|(default,Oct132017,12:02:49)hasthesameoldroundingproblem."{0}".format(float("{0:.1g}".format(0.075)))yields'0.07',not'0.08' – DonMclachlan Feb22'19at19:00 @DonMclachlanI'veaddedanexplanationofwhythisisexpectedinstackoverflow.com/a/56974893/1358308 – SamMason Jul10'19at16:24 Addacomment  |  0 IranintothisaswellbutIneededcontrolovertheroundingtype.Thus,Iwroteaquickfunction(seecodebelow)thatcantakevalue,roundingtype,anddesiredsignificantdigitsintoaccount. importdecimal frommathimportlog10,floor defmyrounding(value,roundstyle='ROUND_HALF_UP',sig=3): roundstyles=['ROUND_05UP','ROUND_DOWN','ROUND_HALF_DOWN','ROUND_HALF_UP','ROUND_CEILING','ROUND_FLOOR','ROUND_HALF_EVEN','ROUND_UP'] power=-1*floor(log10(abs(value))) value='{0:f}'.format(value)#formatvaluetostringtopreventfloatconversionissues divided=Decimal(value)*(Decimal('10.0')**power) roundto=Decimal('10.0')**(-sig+1) ifroundstylenotinroundstyles: print('roundstylemustbeinlist:',roundstyles)##Couldthrownanexceptionhereifyouwant. return_val=decimal.Decimal(divided).quantize(roundto,rounding=roundstyle)*(decimal.Decimal(10.0)**-power) nozero=('{0:f}'.format(return_val)).rstrip('0').rstrip('.')#stripsouttrailing0and. returndecimal.Decimal(nozero) forxinlist(map(float,'-1.2341.23450.03-90.2590.345439123.3111'.split())): print(x,'roundedUP:',myrounding(x,'ROUND_UP',3)) print(x,'roundednormal:',myrounding(x,sig=3)) Share Follow editedSep28'17at17:00 MiriamFarber 16.9k1212goldbadges5353silverbadges7272bronzebadges answeredSep28'17at16:52 drew.raydrew.ray 2111silverbadge33bronzebadges Addacomment  |  0 Thisfunctiondoesanormalroundifthenumberisbiggerthan10**(-decimal_positions),otherwiseaddsmoredecimaluntilthenumberofmeaningfuldecimalpositionsisreached: defsmart_round(x,decimal_positions): dp=-int(math.log10(abs(x)))ifx!=0.0elseint(0) returnround(float(x),decimal_positions+dpifdp>0elsedecimal_positions) Hopeithelps. Share Follow editedJul19'18at11:50 answeredJul19'18at9:38 EttoreGalliEttoreGalli 59344silverbadges2020bronzebadges Addacomment  |  0 https://stackoverflow.com/users/1391441/gabriel,doesthefollowingaddressyourconcernaboutrnd(.075,1)? Caveat:returnsvalueasafloat defround_to_n(x,n): fmt='{:1.'+str(n)+'e}'#gives1.nfigures p=fmt.format(x).split('e')#getmantissaandexponent #round"extra"figureoffmantissa p[0]=str(round(float(p[0])*10**(n-1))/10**(n-1)) returnfloat(p[0]+'e'+p[1])#convertstrtofloat >>>round_to_n(750,2) 750.0 >>>round_to_n(750,1) 800.0 >>>round_to_n(.0750,2) 0.075 >>>round_to_n(.0750,1) 0.08 >>>math.pi 3.141592653589793 >>>round_to_n(math.pi,7) 3.141593 Share Follow editedFeb22'19at19:32 answeredFeb22'19at18:46 DonMclachlanDonMclachlan 40144silverbadges88bronzebadges Addacomment  |  0 Thisreturnsastring,sothatresultswithoutfractionalparts,andsmallvalueswhichwouldotherwiseappearinEnotationareshowncorrectly: defsigfig(x,num_sigfig): num_decplace=num_sigfig-int(math.floor(math.log10(abs(x))))-1 return'%.*f'%(num_decplace,round(x,num_decplace)) Share Follow answeredMar15'19at12:04 GnubieGnubie 2,50744goldbadges2424silverbadges3636bronzebadges Addacomment  |  0 Givenaquestionsothoroughlyansweredwhynotaddanother Thissuitsmyaestheticalittlebetter,thoughmanyoftheabovearecomparable importnumpyasnp number=-456.789 significantFigures=4 roundingFactor=significantFigures-int(np.floor(np.log10(np.abs(number))))-1 rounded=np.round(number,roundingFactor) string=rounded.astype(str) print(string) Thisworksforindividualnumbersandnumpyarrays,andshouldfunctionfinefornegativenumbers. There'soneadditionalstepwemightadd-np.round()returnsadecimalnumberevenifroundedisaninteger(i.e.forsignificantFigures=2wemightexpecttogetback-460butinsteadweget-460.0).Wecanaddthissteptocorrectforthat: ifroundingFactor<=0: rounded=rounded.astype(int) Unfortunately,thisfinalstepwon'tworkforanarrayofnumbers-I'llleavethattoyoudearreadertofigureoutifyouneed. Share Follow answeredAug3'19at8:59 zephyrzephyr 21522silverbadges1313bronzebadges Addacomment  |  0 importmath defsig_dig(x,n_sig_dig): num_of_digits=len(str(x).replace(".","")) ifn_sig_dig>=num_of_digits: returnx n=math.floor(math.log10(x)+1-n_sig_dig) result=round(10**-n*x)*10**n returnfloat(str(result)[:n_sig_dig+1]) >>>sig_dig(1234243,3) >>>sig_dig(243.3576,5) 1230.0 243.36 Share Follow editedMar27'20at17:37 answeredMar26'20at21:29 LetzerWilleLetzerWille 4,55433goldbadges1919silverbadges2424bronzebadges 4 1 Thisfunctionisnotdoingwhatitshould.sig_dig(1234243,3)shouldbe1230000andnot1230.0. – timmey Nov6'20at12:38 Ifyoujustreturntheresult,thenitwillbefine(i.e.removethelastlineofyourfunction). – timmey Nov6'20at12:47 Also,youshouldtaketheabsolutevaluemath.log10(abs(x))todealwithnegativenumbers.Giventhetwocorrections,itlookslikeitworkswellandisquitefast. – timmey Nov6'20at13:21 It'sunlikelyit'sfast,becauseitusesmath.log10 – TomSwirly Jul29at8:14 Addacomment  |  0 Mostoftheseanswersinvolvethemath,decimaland/ornumpyimportsoroutputvaluesasstrings.Hereisasimplesolutioninbasepythonthathandlesbothlargeandsmallnumbersandoutputsafloat: defsig_fig_round(number,digits=3): power="{:e}".format(number).split('e')[1] returnround(number,-(int(power)-digits)) Share Follow answeredDec16'20at18:23 JoshDuranJoshDuran 1122bronzebadges Addacomment  |  0 Asimplevariantusingthestandarddecimallibrary fromdecimalimportDecimal defto_significant_figures(v:float,n_figures:int)->str: d=Decimal(v) d=d.quantize(Decimal((0,(),d.adjusted()-n_figures+1))) returnstr(d.quantize(Decimal(1))ifd==d.to_integral()elsed.normalize()) Testingit >>>to_significant_figures(1.234567,3) '1.23' >>>to_significant_figures(1234567,3) '1230000' >>>to_significant_figures(1.23,7) '1.23' >>>to_significant_figures(123,7) '123' Share Follow answeredSep4at21:47 IgorMikushkinIgorMikushkin 1,0091313silverbadges1919bronzebadges Addacomment  |  0 Thisfunctiontakesbothpositiveandnegativenumbersanddoesthepropersignificantdigitrounding. frommathimportfloor defsignificant_arithmetic_rounding(n,d): ''' Thisfunctiontakesafloatingpointnumberandtheno.ofsignificantdigitd,performsignificantdigits arithmeticroundingandreturnsthefloatingpointnumberafterrounding ''' ifn==0: return0 else: #Checkingwhethertheno.isnegativeorpositive.Ifitisnegativewewilltaketheabsolutevalueofitandproceed neg_flag=0 ifn<0: neg_flag=1 n=abs(n) n1=n #Countingtheno.ofdigitstotheleftofthedecimalpointintheno. ld=0 while(n1>=1): n1/=10 ld+=1 n1=n #Countingtheno.ofzerostotherightofthedecimalpointandbeforethefirstsignificantdigitintheno. z=0 ifld==0: while(n1<=0.1): n1*=10 z+=1 n1=n #No.ofdigitstobeconsideredafterdecimalforrounding rd=(d-ld)+z n1*=10**rd #Increaseby0.5andtakethefloorvalueforrounding n1=floor(n1+0.5) #Placingthedecimalpointatproperposition n1/=10**rd #Iftheoriginalnumberisnegativethenmakeitnegative ifneg_flag==1: n1=0-n1 returnn1 Testing: >>>significant_arithmetic_rounding(1234,3) 1230.0 >>>significant_arithmetic_rounding(123.4,3) 123.0 >>>significant_arithmetic_rounding(0.0012345,3) 0.00123 >>>significant_arithmetic_rounding(-0.12345,3) -0.123 >>>significant_arithmetic_rounding(-30.15345,3) -30.2 Share Follow editedDec7at18:29 answeredDec7at15:08 AyanDeAyanDe 111bronzebadge Newcontributor AyanDeisanewcontributortothissite.Takecareinaskingforclarification,commenting,andanswering. CheckoutourCodeofConduct. Addacomment  |  YourAnswer ThanksforcontributingananswertoStackOverflow!Pleasebesuretoanswerthequestion.Providedetailsandshareyourresearch!Butavoid…Askingforhelp,clarification,orrespondingtootheranswers.Makingstatementsbasedonopinion;backthemupwithreferencesorpersonalexperience.Tolearnmore,seeourtipsonwritinggreatanswers. Draftsaved Draftdiscarded Signuporlogin SignupusingGoogle SignupusingFacebook SignupusingEmailandPassword Submit Postasaguest Name Email Required,butnevershown PostYourAnswer Discard Byclicking“PostYourAnswer”,youagreetoourtermsofservice,privacypolicyandcookiepolicy Nottheansweryou'relookingfor?Browseotherquestionstaggedpythonmathroundingsignificant-digitsoraskyourownquestion. TheOverflowBlog Smashingbugstosetaworldrecord:AWSBugBust Podcast399:ZerotoMVPwithoutprovisioningadatabase FeaturedonMeta Reducingtheweightofourfooter NewresponsiveActivitypage Communityinputneeded:Therulesforcollectivesarticles A/BtestingontheAskpage Linked 2 Roundnumberwithvariablepowertotwodigitsaccuracy 2 Howtofloornumberstowholenumberinpython -3 Roundtotwoplaces(notdecimalplaces)python 0 Pythonround-Twodecidingdecimals 0 ExponentialtoFloat(GettingALLdecimalnumbersofFloat) 1 Howtostringformatafloattothe10sor100splace? 0 Formattingfloatssotheyallhavethesametotaldigits(ex1.234,456.7) 0 Printingto3significantfiguresinpython -1 Roundanumbertoaspecificnumberofsigfigspython 3494 Isfloatingpointmathbroken? Seemorelinkedquestions Related 6032 HowdoImergetwodictionariesinasingleexpression(takeunionofdictionaries)? 6448 HowdoIcheckwhetherafileexistswithoutexceptions? 6494 WhataremetaclassesinPython? 1386 HowtoroundanumbertondecimalplacesinJava 5022 HowcanIsafelycreateanesteddirectoryinPython? 2714 HowdoyouchangethesizeoffiguresdrawnwithMatplotlib? 7077 DoesPythonhaveaternaryconditionaloperator? 3418 HowtogetthecurrenttimeinPython 3156 HowdoIconcatenatetwolistsinPython? 3441 Howtoroundtoatmost2decimalplaces,ifnecessary? HotNetworkQuestions Whattypesofenemieswouldatwo-handedsledgehammerbeusefulagainstinamedievalfantasysetting? Isthereawordorphrasethatdescribesoldarticlespublishedagain? AfterourfirstZoominterview,mypotentialsupervisoraskedmetoprepareapresentationforthenextZoommeeting WhatwastheBigBangmodeloriginallycalled? Howtoreplaceabrokenfronthubonavintagesteelwheelfromavintagesteelbike? Isubmittedapaperoverayearagoandhavenotheardback.WhatshouldIdo? Authorshipofastudentwhopublishedseparatelywithoutpermission DoIholdthecopyrightontestanswers? AoCG2021Day13:Defraginaction! Log-linearandGLM(Poisson)regression WhattoavoidwhenwritingdistantandinconsequentialPOVs? What'sthemeaningof"Manweißhaltgefühltnichts"? Whyusediamond-likecarboninsteadofdiamond? Whydoesthisnewdirectoryhavealinkcountof3? DidYosef'schildreninheritanyoftherichesthatYosefaccumulatedasaVizierofEgypt? MeasuringACwithaDCoffsetusingadigitalmulti-meter PredictingwithaGLM 555Astable:Separatechargeanddischargeresistors? WheredoestheextraspacecomefromafteracapitalPinmathmode? Shouldoneadjustp-valuesformultipletestingcorrectionsinresearch? Whathappenstoafamiliarifthemasterdiesandisbroughtback? What'sthedifferencebetween«fonctionner»and«sefonctionner»? Residentialfiberroughin? mixedintegerprogrammingwithifthenstatementfortwobinarysequences morehotquestions Questionfeed SubscribetoRSS Questionfeed TosubscribetothisRSSfeed,copyandpastethisURLintoyourRSSreader. lang-py Yourprivacy Byclicking“Acceptallcookies”,youagreeStackExchangecanstorecookiesonyourdeviceanddiscloseinformationinaccordancewithourCookiePolicy. Acceptallcookies Customizesettings  



請為這篇文章評分?