Cách làm tròn số đến số liệu quan trọng trong Python


148

Tôi cần làm tròn một float để được hiển thị trong UI. Ví dụ, với một con số quan trọng:

1234 -> 1000

0,12 -> 0,1

0,012 -> 0,01

0,062 -> 0,06

6253 -> 6000

1999 -> 2000

Có một cách hay để làm điều này bằng thư viện Python hay tôi phải tự viết nó?


2
Bạn chỉ định dạng đầu ra? Bạn đang hỏi về điều này? docs.python.org/l Library / stdtypes.html # String-formatted hay này? docs.python.org/l Library / chuỗi.html
S.Lott

bạn mong đợi sản lượng nào cho 0,062 và 6253?
lamirap

Các gói chính xác bây giờ làm điều này. Câu trả lời của tôi đăng chi tiết làm thế nào điều này áp dụng.
William Rusnack

Câu trả lời:


146

Bạn có thể sử dụng số âm để làm tròn số nguyên:

>>> round(1234, -3)
1000.0

Do đó, nếu bạn chỉ cần chữ số có nghĩa nhất:

>>> from math import log10, floor
>>> def round_to_1(x):
...   return round(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

Có lẽ bạn sẽ phải chăm sóc biến float thành số nguyên nếu nó lớn hơn 1.


3
Đây là giải pháp chính xác. Sử dụng log10là cách thích hợp duy nhất để xác định làm thế nào để làm tròn nó.
Wolph

73
round_to_n = lambda x, n: round (x, -int (floor (log10 (x))) + (n - 1))
Roy Hyunjin Han

28
Bạn nên sử dụng log10(abs(x)), nếu không các số âm sẽ thất bại ( x == 0Tất nhiên là xử lý riêng)
Tobias Kienzler 30/07/13

2
Tôi đã tạo ra một gói thực hiện điều này ngay bây giờ và có lẽ dễ dàng và mạnh mẽ hơn gói này. Liên kết bài , Liên kết Repo . Hi vọng điêu nay co ich!
William Rusnack

2
round_to_n = lambda x, n: x if x == 0 else round(x, -int(math.floor(math.log10(abs(x)))) + (n - 1))bảo vệ chống lại x==0x<0cảm ơn bạn @RoyHyunjinHan và @TobiasKienzler. Không được bảo vệ chống lại không xác định như math.inf hoặc rác như Không, v.v.
AJP

98

% g trong định dạng chuỗi sẽ định dạng một số float được làm tròn đến một số số liệu có ý nghĩa. Đôi khi, nó sẽ sử dụng ký hiệu khoa học 'e', ​​vì vậy hãy chuyển đổi chuỗi được làm tròn trở lại thành float sau đó thông qua định dạng chuỗi% s.

>>> '%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'

7
Yêu cầu của OP là năm 1999 được định dạng là '2000', không phải là '2000.0'. Tôi không thể thấy một cách tầm thường để thay đổi phương pháp của bạn để đạt được điều này.
Tim Martin

1
Đó chỉ là những gì tôi luôn muốn! bạn tìm cái này ở đâu
djhaskin987

12
Lưu ý rằng hành vi của% g không phải lúc nào cũng đúng. Đặc biệt, nó luôn cắt các số 0 ở ngay cả khi chúng có ý nghĩa. Số 1.23400 có 6 chữ số có nghĩa, nhưng "% .6g"% (1.23400) sẽ dẫn đến "1.234" không chính xác. Thêm chi tiết trong bài đăng trên blog này: randlet.com/blog/python-significant-fftime-format
randlet

3
Cũng giống như các phương pháp trong câu trả lời Evgeny, điều này không đúng tròn 0.075đến 0.08. Nó trở lại 0.07thay thế.
Gabriel

1
round_sig = lambda f,p: float(('%.' + str(p) + 'e') % f)cho phép bạn điều chỉnh số lượng chữ số có nghĩa!
denizb

49

Nếu bạn muốn có hơn 1 số thập phân có ý nghĩa (nếu không giống như Evgeny):

>>> from math import log10, floor
>>> def round_sig(x, sig=2):
...   return round(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

8
round_sig (-0.0232) -> lỗi miền toán học, bạn có thể muốn thêm abs () vào đó;)
dgorissen

2
Cũng giống như các phương pháp trong câu trả lời của Evgeny và Peter Graham, điều này không đúng tròn 0.075đến 0.08. Nó trở lại 0.07thay thế.
Gabriel

3
Ngoài ra, nó không thành công cho round_sig (0).
Yuval Atzmon

2
@Gabriel Đó là một "tính năng" tích hợp của python chạy trên máy tính của bạn và thể hiện chính nó trong hành vi của chức năng round. docs.python.org/2/tutorial/floatingpoint.html#tut-fp-issues
Novice C

1
@Gabriel Tôi đã thêm một câu trả lời giải thích lý do tại sao bạn nên mong đợi lấy lại 0,7 từ làm tròn "0,075"! xem stackoverflow.com/a/56974893/1353308
Sam Mason

30
f'{float(f"{i:.1g}"):g}'
# Or with Python <3.6,
'{:g}'.format(float('{:.1g}'.format(i)))

Giải pháp này khác với tất cả các giải pháp khác vì:

  1. chính xác giải quyết câu hỏi OP
  2. không cần thêm gói
  3. không cần bất kỳ hàm phụ trợ do người dùng định nghĩa hoặc hoạt động toán học

Đối với một số lượng nđáng kể các số liệu quan trọng, bạn có thể sử dụng:

print('{:g}'.format(float('{:.{p}g}'.format(i, p=n))))

Kiểm tra:

a = [1234, 0.12, 0.012, 0.062, 6253, 1999, -3.14, 0., -48.01, 0.75]
b = ['{:g}'.format(float('{:.1g}'.format(i))) for i in a]
# b == ['1000', '0.1', '0.01', '0.06', '6000', '2000', '-3', '0', '-50', '0.8']

Lưu ý : với giải pháp này, không thể tự động điều chỉnh số lượng các số liệu có ý nghĩa từ đầu vào vì không có cách tiêu chuẩn để phân biệt các số với các số 0 khác nhau ( 3.14 == 3.1400). Nếu bạn cần làm như vậy, thì các hàm không chuẩn như các hàm được cung cấp trong gói chính xác là cần thiết.


FYI: Tôi đã tìm thấy giải pháp này một cách độc lập với eddygeek trong khi tôi đang cố gắng giải quyết vấn đề tương tự trong một trong những mã của tôi. Bây giờ tôi nhận ra rằng giải pháp của tôi rõ ràng là gần giống với giải pháp của anh ấy (tôi chỉ nhận thấy đầu ra sai lầm và không buồn đọc mã, lỗi của tôi). Có lẽ một nhận xét ngắn bên dưới câu trả lời của anh ta là đủ thay vì một câu trả lời mới ... Sự khác biệt duy nhất (chính) là việc sử dụng hai lần của bộ :gđịnh dạng bảo toàn số nguyên.
Falken

Wow, câu trả lời của bạn cần phải thực sự được đọc từ trên xuống dưới;) Thủ thuật hai lần này là bẩn, nhưng gọn gàng. (Lưu ý rằng 1999 được định dạng như 2000.0 gợi ý 5 chữ số có nghĩa, do đó nó phải đi qua {:g}lại.) Nói chung, các số nguyên có các số 0 ở cuối không rõ ràng đối với các số liệu có ý nghĩa, trừ khi một số kỹ thuật (như vượt quá mức đáng kể cuối cùng) được sử dụng.
Tomasz Gandor

8

Tôi đã tạo ra gói chính xác để làm những gì bạn muốn. Nó cho phép bạn đưa ra con số của mình nhiều hơn hoặc ít hơn.

Nó cũng đưa ra các ký hiệu tiêu chuẩn, khoa học và kỹ thuật với một số lượng đáng kể các số liệu quan trọng.

Trong câu trả lời được chấp nhận có dòng

>>> round_to_1(1234243)
1000000.0

Điều đó thực sự chỉ định 8 quả sung sig. Đối với số 1234243, thư viện của tôi chỉ hiển thị một con số đáng kể:

>>> from to_precision import to_precision
>>> to_precision(1234243, 1, 'std')
'1000000'
>>> to_precision(1234243, 1, 'sci')
'1e6'
>>> to_precision(1234243, 1, 'eng')
'1e6'

Nó cũng sẽ làm tròn con số đáng kể cuối cùng và có thể tự động chọn ký hiệu nào sẽ sử dụng nếu ký hiệu không được chỉ định:

>>> to_precision(599, 2)
'600'
>>> to_precision(1164, 2)
'1.2e3'

Bây giờ tôi đang tìm kiếm tương tự nhưng áp dụng cho một con gấu trúc df
mhoff

@mhoff có lẽ bạn có thể sử dụng bản đồ gấu trúc với lambda. lambda x: to_precision(x, 2)
William Rusnack

Thêm phần này vào (PyPI) [ pypi.org/] . Không có gì như thế này tồn tại trên đó, theo như tôi có thể nói.
Morgoth

đây là một gói tuyệt vời nhưng tôi nghĩ rằng hầu hết các tính năng hiện có trong mô-đun
sigfig

1
nó có một lỗi: std_notation (9.999999999999999e-05, 3) đưa ra: '0,00010' chỉ có 2 chữ số có nghĩa
Boris Mulder

5

Để làm tròn một số nguyên thành 1 con số đáng kể, ý tưởng cơ bản là chuyển đổi nó thành một dấu phẩy động có 1 chữ số trước điểm và làm tròn số đó, sau đó chuyển đổi nó trở lại kích thước số nguyên ban đầu.

Để làm điều này, chúng ta cần biết công suất lớn nhất nhỏ hơn 10 so với số nguyên. Chúng ta có thể sử dụng sàn của hàm log 10 cho việc này.

from math import log10, floor
def round_int(i,places):
    if i == 0:
        return 0
    isign = i/abs(i)
    i = abs(i)
    if i < 1:
        return 0
    max10exp = floor(log10(i))
    if max10exp+1 < places:
        return i
    sig10pow = 10**(max10exp-places+1)
    floated = i*1.0/sig10pow
    defloated = round(floated)*sig10pow
    return int(defloated*isign)

1
Thêm một cho giải pháp hoạt động mà không có vòng của python (.., chữ số) và không có chuỗi nào được đính kèm!
Steve Rogers

5

Để trả lời trực tiếp câu hỏi, đây là phiên bản của tôi bằng cách đặt tên từ hàm R :

import math

def signif(x, digits=6):
    if x == 0 or not math.isfinite(x):
        return x
    digits -= math.ceil(math.log10(abs(x)))
    return round(x, digits)

Lý do chính của tôi để đăng câu trả lời này là các ý kiến ​​phàn nàn rằng "0,075" làm tròn thành 0,07 thay vì 0,08. Điều này là do, được chỉ ra bởi "Novice C", với sự kết hợp của số học dấu phẩy động có cả độ chính xác hữu hạn và biểu diễn cơ số 2 . Số gần nhất với 0,075 thực sự có thể được biểu diễn nhỏ hơn một chút, do đó làm tròn xuất hiện khác với những gì bạn có thể mong đợi một cách ngây thơ.

Cũng lưu ý rằng điều này áp dụng cho bất kỳ việc sử dụng số học dấu phẩy động không thập phân nào, ví dụ cả C và Java đều có cùng một vấn đề.

Để hiển thị chi tiết hơn, chúng tôi yêu cầu Python định dạng số theo định dạng "hex":

0.075.hex()

cung cấp cho chúng tôi : 0x1.3333333333333p-4. Lý do để làm điều này là biểu diễn thập phân bình thường thường liên quan đến làm tròn và do đó không phải là cách máy tính thực sự "nhìn thấy" số. Nếu bạn chưa quen với định dạng này, một vài tài liệu tham khảo hữu ích là tài liệu Pythontiêu chuẩn C .

Để cho thấy những con số này hoạt động như thế nào một chút, chúng ta có thể quay lại điểm xuất phát của mình bằng cách thực hiện:

0x13333333333333 / 16**13 * 2**-4

Nên in ra 0.075. 16**13là bởi vì có 13 chữ số thập lục phân sau dấu thập phân và 2**-4là bởi vì số mũ hex là cơ số 2.

Bây giờ chúng tôi có một số ý tưởng về cách nổi được thể hiện, chúng tôi có thể sử dụng decimalmô-đun để cung cấp cho chúng tôi chính xác hơn, cho chúng tôi thấy những gì đang xảy ra:

from decimal import Decimal

Decimal(0x13333333333333) / 16**13 / 2**4

đưa ra: 0.07499999999999999722444243844và hy vọng giải thích lý do tại sao round(0.075, 2)đánh giá0.07


1
Đây là một lời giải thích tuyệt vời về lý do tại sao 0,075 được làm tròn xuống 0,07 ở cấp mã , nhưng chúng tôi (trong khoa học vật lý) đã được dạy để luôn luôn làm tròn không xuống. Vì vậy, hành vi dự kiến ​​thực sự có 0,08 do đó, các vấn đề chính xác về dấu phẩy động bất chấp.
Gabriel

1
Tôi không chắc chắn sự nhầm lẫn của bạn là ở đâu: khi bạn nhập 0,075, bạn thực sự nhập ~ 0,07499 (như trên), làm tròn theo quy tắc toán học thông thường. nếu bạn đang sử dụng một loại dữ liệu (như dấu phẩy động thập phân ) có thể đại diện cho 0,075 thì nó thực sự sẽ làm tròn thành 0,08
Sam Mason

Tôi không bối rối. Khi tôi nhập 0,075, tôi thực sự nhập 0,075. Bất cứ điều gì xảy ra trong toán học dấu phẩy động bên trong mã tôi không quan tâm.
Gabriel

@Gabriel: Và nếu bạn đã cố tình nhập 0.074999999999999999, bạn sẽ mong đợi gì trong trường hợp đó?
Đánh dấu Dickinson

@MarkDickinson mà phụ thuộc. Một con số đáng kể: 0,07, hai: 0,075.
Gabriel

4
def round_to_n(x, n):
    if not x: return 0
    power = -int(math.floor(math.log10(abs(x)))) + (n - 1)
    factor = (10 ** power)
    return round(x * factor) / factor

round_to_n(0.075, 1)      # 0.08
round_to_n(0, 1)          # 0
round_to_n(-1e15 - 1, 16) # 1000000000000001.0

Hy vọng sử dụng tốt nhất tất cả các câu trả lời ở trên (trừ việc có thể đặt nó dưới dạng lambda một dòng;)). Chưa khám phá, hãy chỉnh sửa câu trả lời này:

round_to_n(1e15 + 1, 11)  # 999999999999999.9

4

Tôi đã sửa đổi giải pháp của indgar để xử lý số âm và số nhỏ (bao gồm số không).

from math import log10, floor
def round_sig(x, sig=6, small_value=1.0e-9):
    return round(x, sig - int(floor(log10(max(abs(x), abs(small_value))))) - 1)

Tại sao không chỉ kiểm tra xem x == 0? Nếu bạn yêu thích một lớp lót, chỉ cần return 0 if x==0 else round(...).
pjvandehaar

2
@pjvandehaar, bạn đúng với trường hợp chung và tôi nên đưa nó vào. Ngoài ra, đối với các phép tính số tôi cần thực hiện, đôi khi chúng tôi nhận được các số như 1e-15. Trong ứng dụng của chúng tôi, chúng tôi muốn so sánh hai số nhỏ (một trong số đó có thể bằng 0) được coi là bằng nhau. Ngoài ra, một số người muốn làm tròn số nhỏ (có thể là 1e-9, 1e-15 hoặc thậm chí 1e-300) về không.
ryan281

1
Hấp dẫn. Cảm ơn đã giải thích điều đó. Trong trường hợp đó, tôi thực sự thích giải pháp này.
pjvandehaar

@Morgoth Đây là một vấn đề thú vị và khó khăn. Như bạn đã chỉ ra, giá trị in không hiển thị 3 chữ số có nghĩa, nhưng giá trị này là chính xác (ví dụ 0.970 == 0.97). Tôi nghĩ rằng bạn có thể sử dụng một số giải pháp in khác như f'{round_sig(0.9701, sig=3):0.3f}'nếu bạn muốn in số không.
ryan281

3

Nếu bạn muốn làm tròn mà không liên quan đến chuỗi, liên kết tôi tìm thấy bị chôn vùi trong các ý kiến ​​trên:

http://code.activestate.com/lists/python-tutor/70739/

tấn công tôi là tốt nhất. Sau đó, khi bạn in với bất kỳ mô tả định dạng chuỗi nào, bạn sẽ có được đầu ra hợp lý và bạn có thể sử dụng biểu diễn số cho các mục đích tính toán khác.

Mã tại liên kết là một lớp lót ba: def, doc và return. Nó có một lỗi: bạn cần kiểm tra sự bùng nổ logarit. Điều đó thật dễ. So sánh đầu vào với sys.float_info.min. Giải pháp hoàn chỉnh là:

import sys,math

def tidy(x, n):
"""Return 'x' rounded to 'n' significant digits."""
y=abs(x)
if y <= sys.float_info.min: return 0.0
return round( x, int( n-math.ceil(math.log10(y)) ) )

Nó hoạt động cho bất kỳ giá trị số vô hướng nào và n có thể là một floatnếu bạn cần thay đổi phản hồi vì một số lý do. Bạn thực sự có thể đẩy giới hạn tới:

sys.float_info.min*sys.float_info.epsilon

mà không gây ra lỗi, nếu vì một lý do nào đó bạn đang làm việc với các giá trị rất nhỏ.


2

Tôi không thể nghĩ ra bất cứ điều gì có thể xử lý việc này ra khỏi hộp. Nhưng nó được xử lý khá tốt cho các số dấu phẩy động.

>>> round(1.2322, 2)
1.23

Số nguyên là khó khăn hơn. Chúng không được lưu trữ dưới dạng cơ sở 10 trong bộ nhớ, vì vậy những nơi quan trọng không phải là điều tự nhiên phải làm. Nó khá tầm thường để thực hiện một khi chúng là một chuỗi.

Hoặc cho số nguyên:

>>> def intround(n, sigfigs):
...   n = str(n)
...   return n[:sigfigs] + ('0' * (len(n)-(sigfigs)))

>>> intround(1234, 1)
'1000'
>>> intround(1234, 2)

Nếu bạn muốn tạo một hàm xử lý bất kỳ số nào, sở thích của tôi sẽ là chuyển đổi cả hai thành chuỗi và tìm vị trí thập phân để quyết định nên làm gì:

>>> def roundall1(n, sigfigs):
...   n = str(n)
...   try:
...     sigfigs = n.index('.')
...   except ValueError:
...     pass
...   return intround(n, sigfigs)

Một lựa chọn khác là kiểm tra loại. Điều này sẽ kém linh hoạt hơn rất nhiều và có thể sẽ không chơi độc đáo với các số khác như Decimalcác đối tượng:

>>> def roundall2(n, sigfigs):
...   if type(n) is int: return intround(n, sigfigs)
...   else: return round(n, sigfigs)

Chỉ lộn xộn với các chuỗi sẽ không làm tròn số. 1999 làm tròn thành 1 con số đáng kể là 2000, không phải 1000.
Peter Graham

Có một cuộc thảo luận tốt về vấn đề này lưu giữ tại ActiveState code.activestate.com/lists/python-tutor/70739
Tim McNamara

2

Câu trả lời được đăng là tốt nhất có sẵn khi được đưa ra, nhưng nó có một số hạn chế và không tạo ra các số liệu quan trọng chính xác về mặt kỹ thuật.

numpy.format_float_pose điều kiện hỗ trợ trực tiếp hành vi mong muốn. Đoạn sau trả về số float xđược định dạng thành 4 hình quan trọng, với ký hiệu khoa học bị loại bỏ.

import numpy as np
x=12345.6
np.format_float_positional(x, precision=4, unique=False, fractional=False, trim='k')
> 12340.

Tài liệu (được chuyển đến numpy.org/doc/urdy/reference/generated/, ) nói rằng hàm này thực hiện thuật toán Dragon4 (của Steele & White 1990, dl.acm.org/doi/pdf/10.1145/93542.93559 ). Nó tạo ra kết quả khó chịu, ví dụ print(*[''.join([np.format_float_positional(.01*a*n,precision=2,unique=False,fractional=False,trim='k',pad_right=5) for a in [.99, .999, 1.001]]) for n in [8,9,10,11,12,19,20,21]],sep='\n'). Tôi đã không kiểm tra Dragon4.
Rainald62

0

Tôi cũng gặp phải vấn đề này nhưng tôi cần kiểm soát kiểu làm tròn. Vì vậy, tôi đã viết một hàm nhanh (xem mã bên dưới) có thể lấy giá trị, kiểu làm tròn và các chữ số có nghĩa mong muốn vào tài khoản.

import decimal
from math import log10, floor

def myrounding(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) #format value to string to prevent float conversion issues
    divided = Decimal(value) * (Decimal('10.0')**power) 
    roundto = Decimal('10.0')**(-sig+1)
    if roundstyle not in roundstyles:
        print('roundstyle must be in list:', roundstyles) ## Could thrown an exception here if you want.
    return_val = decimal.Decimal(divided).quantize(roundto,rounding=roundstyle)*(decimal.Decimal(10.0)**-power)
    nozero = ('{0:f}'.format(return_val)).rstrip('0').rstrip('.') # strips out trailing 0 and .
    return decimal.Decimal(nozero)


for x in list(map(float, '-1.234 1.2345 0.03 -90.25 90.34543 9123.3 111'.split())):
    print (x, 'rounded UP: ',myrounding(x,'ROUND_UP',3))
    print (x, 'rounded normal: ',myrounding(x,sig=3))

0

Sử dụng định dạng kiểu python 2.6+ mới (vì% -style không được dùng nữa):

>>> "{0}".format(float("{0:.1g}".format(1216)))
'1000.0'
>>> "{0}".format(float("{0:.1g}".format(0.00356)))
'0.004'

Trong python 2.7+, bạn có thể bỏ qua các 0s hàng đầu .


Với phiên bản nào của trăn? Python 3.6.3 | Anaconda, Inc. | (mặc định, ngày 13 tháng 10 năm 2017, 12:02:49) có cùng một vấn đề làm tròn cũ. "{0}". Định dạng (float ("{0: .1g}". Format (0.075))) mang lại '0,07', không phải '0,08'
Don Mclachlan

@DonMclachlan Tôi đã thêm một lời giải thích về lý do tại sao điều này được mong đợi trong stackoverflow.com/a/56974893/1353308
Sam Mason

0

Hàm này thực hiện một vòng bình thường nếu số lớn hơn 10 ** (- binary_poseitions), nếu không thì thêm số thập phân cho đến khi đạt được số lượng vị trí thập phân có ý nghĩa:

def smart_round(x, decimal_positions):
    dp = - int(math.log10(abs(x))) if x != 0.0 else int(0)
    return round(float(x), decimal_positions + dp if dp > 0 else decimal_positions)

Hy vọng nó giúp.


0

https://stackoverflow.com/users/1391441/gabriel , địa chỉ nào sau đây bạn quan tâm về rnd (.075, 1)? Caveat: trả về giá trị dưới dạng float

def round_to_n(x, n):
    fmt = '{:1.' + str(n) + 'e}'    # gives 1.n figures
    p = fmt.format(x).split('e')    # get mantissa and exponent
                                    # round "extra" figure off mantissa
    p[0] = str(round(float(p[0]) * 10**(n-1)) / 10**(n-1))
    return float(p[0] + 'e' + p[1]) # convert str to float

>>> 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

0

Điều này trả về một chuỗi, do đó, kết quả không có các phần phân số và các giá trị nhỏ xuất hiện trong ký hiệu E sẽ được hiển thị chính xác:

def sigfig(x, num_sigfig):
    num_decplace = num_sigfig - int(math.floor(math.log10(abs(x)))) - 1
    return '%.*f' % (num_decplace, round(x, num_decplace))

0

Đưa ra một câu hỏi được trả lời kỹ lưỡng tại sao không thêm một câu hỏi khác

Điều này phù hợp với thẩm mỹ của tôi tốt hơn một chút, mặc dù nhiều điều ở trên là tương đương

import numpy as np

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)

Điều này hoạt động cho các số riêng lẻ và mảng numpy, và sẽ hoạt động tốt cho các số âm.

Có một bước bổ sung mà chúng tôi có thể thêm - np.round () trả về một số thập phân ngay cả khi được làm tròn là một số nguyên (ví dụ: có nghĩa là đáng kể = 2, chúng tôi có thể mong đợi lấy lại -460 nhưng thay vào đó chúng tôi nhận được -460.0). Chúng ta có thể thêm bước này để sửa lỗi cho điều đó:

if roundingFactor<=0:
    rounded=rounded.astype(int)

Thật không may, bước cuối cùng này sẽ không hoạt động đối với một dãy số - Tôi sẽ để lại cho bạn đọc thân yêu để tìm ra nếu bạn cần.


0

Các sigfig gói / bao thư viện này. Sau khi cài đặt, bạn có thể làm như sau:

>>> from sigfig import round
>>> 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

0
import math

  def sig_dig(x, n_sig_dig):
      num_of_digits = len(str(x).replace(".", ""))
      if n_sig_dig >= num_of_digits:
          return x
      n = math.floor(math.log10(x) + 1 - n_sig_dig)
      result = round(10 ** -n * x) * 10 ** n
      return float(str(result)[: n_sig_dig + 1])


    >>> sig_dig(1234243, 3)
    >>> sig_dig(243.3576, 5)

        1230.0
        243.36
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.