decimal --- Số học dấu phẩy động và dấu phẩy cố định thập phân

Source code: Lib/decimal.py


Mô-đun decimal cung cấp hỗ trợ cho số học dấu phẩy động thập phân được làm tròn chính xác nhanh chóng. Nó cung cấp một số lợi thế so với kiểu dữ liệu float:

  • Thập phân "dựa trên floating-point model được thiết kế dành cho mọi người và nhất thiết phải có nguyên tắc hướng dẫn tối cao -- máy tính phải cung cấp số học hoạt động giống như số học mà mọi người học ở trường." -- đoạn trích từ đặc tả số học thập phân.

  • Số thập phân có thể được biểu diễn chính xác. Ngược lại, các số như 1.12.2 không có biểu diễn chính xác dưới dạng dấu phẩy động nhị phân. Người dùng cuối thường không mong đợi 1.1 + 2.2 hiển thị dưới dạng 3.3000000000000003 như với dấu phẩy động nhị phân.

  • Sự chính xác được chuyển sang số học. Trong dấu phẩy động thập phân, 0.1 + 0.1 + 0.1 - 0.3 chính xác bằng 0. Trong dấu phẩy động nhị phân, kết quả là 5.5511151231257827e-017. Mặc dù gần bằng 0, nhưng sự khác biệt ngăn cản việc kiểm tra tính bằng nhau đáng tin cậy và sự khác biệt có thể tích lũy. Vì lý do này, số thập phân được ưa thích hơn trong các ứng dụng kế toán có tính bất biến đẳng thức nghiêm ngặt.

  • Mô-đun thập phân kết hợp khái niệm về các vị trí quan trọng để 1.30 + 1.202.50. Số 0 ở cuối được giữ để biểu thị ý nghĩa. Đây là cách trình bày thông thường cho các ứng dụng tiền tệ. Đối với phép nhân, phương pháp "sách giáo khoa" sử dụng tất cả các số liệu trong phép nhân. Ví dụ: 1.3 * 1.2 cho 1.56 trong khi 1.30 * 1.20 cho 1.5600.

  • Không giống như dấu phẩy động nhị phân dựa trên phần cứng, mô-đun thập phân có độ chính xác mà người dùng có thể thay đổi (mặc định là 28 vị trí) có thể lớn đến mức cần thiết cho một vấn đề nhất định:

    >>> from decimal import *
    >>> getcontext().prec = 6
    >>> Decimal(1) / Decimal(7)
    Decimal('0.142857')
    >>> getcontext().prec = 28
    >>> Decimal(1) / Decimal(7)
    Decimal('0.1428571428571428571428571429')
    
  • Cả dấu phẩy động nhị phân và thập phân đều được thực hiện theo các tiêu chuẩn đã được công bố. Trong khi kiểu float tích hợp chỉ thể hiện một phần khả năng khiêm tốn của nó thì mô-đun thập phân thể hiện tất cả các phần bắt buộc của tiêu chuẩn. Khi cần, lập trình viên có toàn quyền kiểm soát việc làm tròn và xử lý tín hiệu. Điều này bao gồm một tùy chọn để thực thi số học chính xác bằng cách sử dụng các ngoại lệ để chặn mọi hoạt động không chính xác.

  • Mô-đun thập phân được thiết kế để hỗ trợ "không có thành kiến, cả số học thập phân không làm tròn chính xác (đôi khi được gọi là số học dấu phẩy cố định) và số học dấu phẩy động làm tròn." -- đoạn trích từ đặc tả số học thập phân.

Thiết kế mô-đun tập trung vào ba khái niệm: số thập phân, bối cảnh số học và tín hiệu.

Một số thập phân là bất biến. Nó có dấu, chữ số hệ số và số mũ. Để duy trì ý nghĩa, các chữ số hệ số không cắt bớt các số 0 ở cuối. Số thập phân cũng bao gồm các giá trị đặc biệt như Infinity, -InfinityNaN. Tiêu chuẩn cũng phân biệt -0 với +0.

Ngữ cảnh của số học là môi trường xác định độ chính xác, quy tắc làm tròn, giới hạn số mũ, cờ biểu thị kết quả của các phép toán và trình hỗ trợ bẫy xác định xem tín hiệu có được coi là ngoại lệ hay không. Các tùy chọn làm tròn bao gồm ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_UPROUND_05UP.

Tín hiệu là nhóm các điều kiện đặc biệt phát sinh trong quá trình tính toán. Tùy thuộc vào nhu cầu của ứng dụng, các tín hiệu có thể bị bỏ qua, được coi là thông tin hoặc được coi là ngoại lệ. Các tín hiệu trong mô-đun thập phân là: Clamped, InvalidOperation, DivisionByZero, Inexact, Rounded, Subnormal, Overflow, UnderflowFloatOperation.

Đối với mỗi tín hiệu có một cờ và một bộ kích hoạt bẫy. Khi gặp một tín hiệu, cờ của nó được đặt thành một, sau đó, nếu trình kích hoạt bẫy được đặt thành một, một ngoại lệ sẽ được đưa ra. Cờ có tính dính nên người dùng cần đặt lại chúng trước khi theo dõi phép tính.

Xem thêm

Hướng dẫn bắt đầu nhanh

Cách bắt đầu thông thường khi sử dụng số thập phân là nhập mô-đun, xem ngữ cảnh hiện tại bằng getcontext() và, nếu cần, đặt các giá trị mới cho bẫy chính xác, làm tròn hoặc bật:

>>> từ nhập thập phân *
>>> getcontext()
Bối cảnh(prec=28, làm tròn=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
        chữ hoa=1, kẹp=0, cờ=[], bẫy=[Tràn, DivisionByZero,
        Thao tác không hợp lệ])

>>> getcontext().prec = 7 # Set độ chính xác mới

Các phiên bản thập phân có thể được xây dựng từ số nguyên, chuỗi, số float hoặc bộ dữ liệu. Việc xây dựng từ một số nguyên hoặc số float thực hiện chuyển đổi chính xác giá trị của số nguyên hoặc số float đó. Số thập phân bao gồm các giá trị đặc biệt như NaN viết tắt của "Không phải số", Infinity dương và âm và -0:

>>> getcontext().prec = 28
>>> Số thập phân(10)
Thập phân('10')
>>> Số thập phân('3.14')
Thập phân('3.14')
>>> Số thập phân(3.14)
Thập phân('3.140000000000000124344978758017532527446746826171875')
>>> Thập phân((0, (3, 1, 4), -2))
Thập phân('3.14')
>>> Thập phân(str(2.0 ** 0.5))
Thập phân('1.4142135623730951')
>>> Thập phân(2) ** Thập phân('0.5')
Thập phân('1.414213562373095048801688724')
>>> Số thập phân('NaN')
Thập phân('NaN')
>>> Số thập phân('-Infinity')
Thập phân('-Infinity')

Nếu tín hiệu FloatOperation bị kẹt, việc vô tình trộn lẫn số thập phân và số float trong hàm tạo hoặc so sánh thứ tự sẽ tạo ra một ngoại lệ:

>>> c = getcontext()
>>> c.traps[FloatOperation] = Đúng
>>> Số thập phân(3.14)
Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 1, trong <module>
thập phân.FloatOperation: [<class 'decimal.FloatOperation'>]
>>> Số thập phân('3.5') < 3.7
Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 1, trong <module>
thập phân.FloatOperation: [<class 'decimal.FloatOperation'>]
>>> Số thập phân('3.5') == 3.5
đúng

Added in version 3.3.

Tầm quan trọng của Số thập phân mới chỉ được xác định bởi số chữ số được nhập vào. Độ chính xác của ngữ cảnh và làm tròn chỉ phát huy tác dụng trong các phép tính số học.

>>> getcontext().prec = 6
>>> Số thập phân('3.0')
Thập phân('3.0')
>>> Số thập phân('3.1415926535')
Thập phân('3.1415926535')
>>> Số thập phân('3.1415926535') + Số thập phân('2.7182818285')
Thập phân('5.85987')
>>> getcontext().rounding = ROUND_UP
>>> Số thập phân('3.1415926535') + Số thập phân('2.7182818285')
Thập phân('5.85988')

Nếu vượt quá giới hạn bên trong của phiên bản C, việc xây dựng số thập phân sẽ tăng InvalidOperation:

>>> Thập phân("1e99999999999999999999")
Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 1, trong <module>
thập phân.InvalidOperation: [<class 'decimal.InvalidOperation'>]

Thay đổi trong phiên bản 3.3.

Số thập phân tương tác tốt với phần lớn phần còn lại của Python. Đây là một rạp xiếc bay dấu phẩy động thập phân nhỏ:

>>> data = list(map(Thập phân, '1,34 1,87 3,45 2,35 1,00 0,03 9,25'.split()))
>>> tối đa(dữ liệu)
Thập phân('9.25')
>>> phút(dữ liệu)
Thập phân('0.03')
>>> sắp xếp(dữ liệu)
[Thập phân('0.03'), Thập phân('1.00'), Thập phân('1.34'), Thập phân('1.87'),
 Thập phân('2.35'), Thập phân('3.45'), Thập phân('9.25')]
>>> tổng (dữ liệu)
Thập phân('19.29')
>>> a,b,c = dữ liệu[:3]
>>> str(a)
'1,34'
>>> thả nổi(a)
1,34
>>> vòng(a, 1)
Thập phân('1.3')
>>> int(a)
1
>>> một * 5
Thập phân('6.70')
>>> a * b
Thập phân('2.5058')
>>> c % một
Thập phân('0.77')

Số thập phân có thể được định dạng (có format() tích hợp hoặc dây f) theo dấu phẩy cố định hoặc ký hiệu khoa học, sử dụng cú pháp định dạng tương tự (xem Đặc tả định dạng ngôn ngữ nhỏ) như loại float dựng sẵn:

>>> định dạng(Thập phân('2.675'), "f")
'2.675'
>>> định dạng(Thập phân('2.675'), ".2f")
'2,68'
>>> f"{Thập phân('2.675'):.2f}"
'2,68'
>>> định dạng(Thập phân('2.675'), ".2e")
'2,68e+0'
>>> với localcontext()  ctx:
... ctx.rounding = ROUND_DOWN
... print(format(Decimal('2.675'), ".2f"))
...
2,67

Và một số hàm toán học cũng có sẵn cho Decimal:

>>> getcontext().prec = 28
>>> Decimal(2).sqrt()
Decimal('1.414213562373095048801688724')
>>> Decimal(1).exp()
Decimal('2.718281828459045235360287471')
>>> Decimal('10').ln()
Decimal('2.302585092994045684017991455')
>>> Decimal('10').log10()
Decimal('1')

Phương thức quantize() làm tròn số thành số mũ cố định. Phương pháp này hữu ích cho các ứng dụng tiền tệ thường làm tròn kết quả đến một số vị trí cố định:

>>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32')
>>> Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)
Decimal('8')

Như được hiển thị ở trên, hàm getcontext() truy cập vào ngữ cảnh hiện tại và cho phép thay đổi cài đặt. Cách tiếp cận này đáp ứng nhu cầu của hầu hết các ứng dụng.

Đối với công việc nâng cao hơn, có thể hữu ích khi tạo các ngữ cảnh thay thế bằng cách sử dụng hàm tạo Context(). Để kích hoạt thay thế, hãy sử dụng chức năng setcontext().

Theo tiêu chuẩn, mô-đun decimal cung cấp hai ngữ cảnh tiêu chuẩn sẵn sàng để sử dụng, BasicContextExtendedContext. Cái trước đặc biệt hữu ích cho việc gỡ lỗi vì nhiều bẫy được kích hoạt:

>>> myothercontext = Ngữ cảnh(prec=60, rounding=ROUND_HALF_DOWN)
>>> setcontext(myothercontext)
>>> Thập phân(1) / Thập phân(7)
Thập phân('0.142857142857142857142857142857142857142857142857142857142857')

>>> Bối cảnh mở rộng
Bối cảnh(prec=9, làm tròn=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
        chữ hoa=1, kẹp=0, cờ=[], bẫy=[])
>>> setcontext(ExtendsContext)
>>> Thập phân(1) / Thập phân(7)
Thập phân('0.142857143')
>>> Thập phân(42) / Thập phân(0)
Thập phân('Vô cực')

>>> setcontext(BasicContext)
>>> Thập phân(42) / Thập phân(0)
Traceback (cuộc gọi gần đây nhất):
  Tệp "<pyshell#143>", dòng 1, trong -toplevel-
    Thập phân(42) / Thập phân(0)
DivisionByZero: x/0

Các bối cảnh cũng có các cờ tín hiệu để theo dõi các điều kiện đặc biệt gặp phải trong quá trình tính toán. Các cờ vẫn được đặt cho đến khi bị xóa rõ ràng, vì vậy tốt nhất nên xóa cờ trước mỗi bộ tính toán được giám sát bằng cách sử dụng phương pháp clear_flags().

>>> setcontext(ExtendsContext)
>>> getcontext().clear_flags()
>>> Thập phân(355) / Thập phân(113)
Thập phân('3.14159292')
>>> getcontext()
Bối cảnh(prec=9, làm tròn=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
        chữ hoa=1, kẹp=0, cờ=[Không chính xác, Làm tròn], bẫy=[])

Mục nhập flags cho thấy phép tính gần đúng hợp lý của pi đã được làm tròn (các chữ số nằm ngoài độ chính xác của ngữ cảnh đã bị loại bỏ) và kết quả là không chính xác (một số chữ số bị loại bỏ khác 0).

Các bẫy riêng lẻ được đặt bằng từ điển trong thuộc tính traps của ngữ cảnh:

>>> setcontext(ExtendsContext)
>>> Thập phân(1) / Thập phân(0)
Thập phân('Vô cực')
>>> getcontext().traps[DivisionByZero] = 1
>>> Thập phân(1) / Thập phân(0)
Traceback (cuộc gọi gần đây nhất):
  Tệp "<pyshell#112>", dòng 1, trong -toplevel-
    Thập phân(1) / Thập phân(0)
DivisionByZero: x/0

Hầu hết các chương trình chỉ điều chỉnh bối cảnh hiện tại một lần, vào lúc bắt đầu chương trình. Và trong nhiều ứng dụng, dữ liệu được chuyển đổi thành Decimal chỉ bằng một lần chuyển đổi bên trong một vòng lặp. Với tập ngữ cảnh và số thập phân được tạo, phần lớn chương trình xử lý dữ liệu không khác gì so với các loại số Python khác.

Đối tượng thập phân

class decimal.Decimal(value='0', context=None)

Xây dựng một đối tượng Decimal mới dựa trên value.

value có thể là một số nguyên, chuỗi, bộ dữ liệu, float hoặc một đối tượng Decimal khác. Nếu không có value, trả về Decimal('0'). Nếu value là một chuỗi, thì nó phải tuân theo cú pháp chuỗi số thập phân sau khi các ký tự khoảng trắng ở đầu và cuối cũng như dấu gạch dưới xuyên suốt đều bị xóa:

dấu ::= '+' | '-'
chữ số ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
chỉ báo ::= 'e' | 'E'
chữ số ::= chữ số [chữ số]...
phần thập phân ::= chữ số '.' [chữ số] | ['.'] chữ số
phần số  ::= chỉ báo [dấu] chữ số
 cực ::= 'Vô cực' | 'Thông tin'
nan ::= 'NaN' [chữ số] | 'sNaN' [chữ số]
giá trị số ::= phần thập phân [phần ] |  cực
chuỗi số ::= [dấu] giá trị số | [] nan

Các chữ số thập phân Unicode khác cũng được phép khi digit xuất hiện ở trên. Chúng bao gồm các chữ số thập phân từ nhiều bảng chữ cái khác (ví dụ: chữ số Ả Rập-Ấn Độ và Devanāgarī) cùng với các chữ số có chiều rộng đầy đủ từ '\uff10' đến '\uff19'. Chữ hoa chữ thường không đáng kể, vì vậy, ví dụ: inf, Inf, INFINITYiNfINity đều là cách viết được chấp nhận cho số dương vô cùng.

Nếu valuetuple thì nó phải có ba thành phần, một dấu (0 cho số dương hoặc 1 cho số âm), một tuple gồm các chữ số và số mũ nguyên. Ví dụ: Decimal((0, (1, 4, 1, 4), -3)) trả về Decimal('1.414').

Nếu valuefloat, giá trị dấu phẩy động nhị phân sẽ được chuyển đổi dễ dàng thành số thập phân tương đương chính xác của nó. Việc chuyển đổi này thường có thể yêu cầu độ chính xác từ 53 chữ số trở lên. Ví dụ: Decimal(float('1.1')) chuyển đổi thành Decimal('1.100000000000000088817841970012523233890533447265625').

Độ chính xác của context không ảnh hưởng đến số lượng chữ số được lưu trữ. Điều đó được xác định hoàn toàn bằng số chữ số trong value. Ví dụ: Decimal('3.00000') ghi lại tất cả năm số không ngay cả khi độ chính xác của ngữ cảnh chỉ là ba.

Mục đích của đối số context là xác định phải làm gì nếu value là một chuỗi không đúng định dạng. Nếu ngữ cảnh bẫy InvalidOperation, một ngoại lệ sẽ xuất hiện; mặt khác, hàm tạo trả về một Số thập phân mới với giá trị NaN.

Sau khi được xây dựng, các đối tượng Decimal là bất biến.

Thay đổi trong phiên bản 3.2: Đối số cho hàm tạo hiện được phép là phiên bản float.

Thay đổi trong phiên bản 3.3: Các đối số float đưa ra một ngoại lệ nếu bẫy FloatOperation được đặt. Theo mặc định, bẫy bị tắt.

Thay đổi trong phiên bản 3.6: Dấu gạch dưới được cho phép để nhóm, như với các chữ số nguyên và dấu phẩy động trong mã.

Các đối tượng dấu phẩy động thập phân chia sẻ nhiều thuộc tính với các kiểu số tích hợp khác như floatint. Tất cả các phép toán thông thường và các phương pháp đặc biệt đều được áp dụng. Tương tự như vậy, các đối tượng thập phân có thể được sao chép, chọn lọc, in, dùng làm khóa từ điển, dùng làm phần tử tập hợp, so sánh, sắp xếp và ép buộc sang loại khác (chẳng hạn như float hoặc int).

Có một số khác biệt nhỏ giữa số học trên các đối tượng thập phân và số học trên số nguyên và số float. Khi toán tử số dư % được áp dụng cho các đối tượng Thập phân, dấu của kết quả là dấu của dividend chứ không phải là dấu của số chia:

>>> (-7) % 4
1
>>> Số thập phân(-7) % Số thập phân(4)
Thập phân('-3')

Toán tử chia số nguyên // hoạt động tương tự, trả về phần nguyên của thương số thực (cắt ngắn về 0) thay vì giá trị sàn của nó, để duy trì nhận dạng thông thường x == (x // y) * y + x % y:

>>> -7 // 4
-2
>>> Số thập phân(-7) // Số thập phân(4)
Thập phân('-1')

Các toán tử %// triển khai các hoạt động remainderdivide-integer (tương ứng) như được mô tả trong thông số kỹ thuật.

Các đối tượng thập phân thường không thể được kết hợp với số float hoặc phiên bản của fractions.Fraction trong các phép toán số học: ví dụ: nỗ lực thêm Decimal vào float sẽ tạo ra TypeError. Tuy nhiên, có thể sử dụng toán tử so sánh của Python để so sánh một phiên bản Decimal x với một số y khác. Điều này tránh các kết quả khó hiểu khi thực hiện so sánh đẳng thức giữa các số thuộc các loại khác nhau.

Thay đổi trong phiên bản 3.2: So sánh kiểu hỗn hợp giữa các phiên bản Decimal và các loại số khác hiện được hỗ trợ đầy đủ.

Ngoài các thuộc tính số tiêu chuẩn, các đối tượng dấu phẩy động thập phân còn có một số phương thức chuyên biệt:

adjusted()

Trả về số mũ đã điều chỉnh sau khi dịch chuyển các chữ số ngoài cùng bên phải của hệ số cho đến khi chỉ còn lại chữ số dẫn đầu: Decimal('321e+5').adjusted() trả về bảy. Được sử dụng để xác định vị trí của chữ số có nghĩa nhất đối với dấu thập phân.

as_integer_ratio()

Trả về một cặp số nguyên (n, d) biểu thị phiên bản Decimal đã cho dưới dạng phân số, ở dạng thấp nhất và có mẫu số dương:

>>> Số thập phân('-3.14').as_integer_ratio()
(-157, 50)

Việc chuyển đổi là chính xác. Tăng OverflowError trên vô số và ValueError trên NaN.

Added in version 3.6.

as_tuple()

Trả về biểu diễn named tuple của số: DecimalTuple(sign, digits, exponent).

canonical()

Trả về mã hóa chuẩn của đối số. Hiện tại, mã hóa của phiên bản Decimal luôn là chuẩn, vì vậy thao tác này trả về đối số của nó không thay đổi.

compare(other, context=None)

So sánh giá trị của hai trường hợp thập phân. compare() trả về một phiên bản thập phân và nếu một trong hai toán hạng là NaN thì kết quả là NaN:

a hoặc b  NaN ==> Thập phân('NaN')
a < b ==> Thập phân('-1')
a == b ==> Thập phân('0')
a > b ==> Thập phân('1')
compare_signal(other, context=None)

Hoạt động này giống hệt với phương pháp compare(), ngoại trừ tất cả tín hiệu NaN. Nghĩa là, nếu cả hai toán hạng đều không phải là NaN báo hiệu thì mọi toán hạng NaN yên tĩnh đều được xử lý như thể nó là NaN báo hiệu.

compare_total(other, context=None)

So sánh hai toán hạng bằng cách sử dụng biểu diễn trừu tượng thay vì giá trị số của chúng. Tương tự như phương pháp compare(), nhưng kết quả đưa ra tổng thứ tự trên các phiên bản Decimal. Hai phiên bản Decimal có cùng giá trị số nhưng cách biểu diễn khác nhau so sánh không bằng nhau theo thứ tự này:

>>> Decimal('12.0').compare_total(Decimal('12'))
Decimal('-1')

Các NaN yên tĩnh và báo hiệu cũng được bao gồm trong tổng thứ tự. Kết quả của hàm này là Decimal('0') nếu cả hai toán hạng có cùng cách biểu diễn, Decimal('-1') nếu toán hạng đầu tiên có tổng thứ tự thấp hơn toán hạng thứ hai và Decimal('1') nếu toán hạng đầu tiên có tổng thứ tự cao hơn toán hạng thứ hai. Xem thông số kỹ thuật để biết chi tiết về tổng đơn hàng.

Hoạt động này không bị ảnh hưởng bởi bối cảnh và yên tĩnh: không có cờ nào được thay đổi và không thực hiện làm tròn. Là một ngoại lệ, phiên bản C có thể tăng InvalidOperation nếu toán hạng thứ hai không thể được chuyển đổi chính xác.

compare_total_mag(other, context=None)

So sánh hai toán hạng bằng cách sử dụng cách biểu diễn trừu tượng thay vì giá trị của chúng như trong compare_total() nhưng bỏ qua dấu của mỗi toán hạng. x.compare_total_mag(y) tương đương với x.copy_abs().compare_total(y.copy_abs()).

Hoạt động này không bị ảnh hưởng bởi bối cảnh và yên tĩnh: không có cờ nào được thay đổi và không thực hiện làm tròn. Là một ngoại lệ, phiên bản C có thể tăng InvalidOperation nếu toán hạng thứ hai không thể được chuyển đổi chính xác.

conjugate()

Chỉ trả về bản thân, phương thức này chỉ tuân theo Thông số thập phân.

copy_abs()

Trả về giá trị tuyệt đối của đối số. Hoạt động này không bị ảnh hưởng bởi bối cảnh và yên tĩnh: không có cờ nào được thay đổi và không thực hiện làm tròn.

copy_negate()

Trả về sự phủ định của đối số. Hoạt động này không bị ảnh hưởng bởi bối cảnh và yên tĩnh: không có cờ nào được thay đổi và không thực hiện làm tròn.

copy_sign(other, context=None)

Trả về một bản sao của toán hạng đầu tiên với dấu được đặt giống với dấu của toán hạng thứ hai. Ví dụ:

>>> Decimal('2.3').copy_sign(Decimal('-1.5'))
Decimal('-2.3')

Hoạt động này không bị ảnh hưởng bởi bối cảnh và yên tĩnh: không có cờ nào được thay đổi và không thực hiện làm tròn. Là một ngoại lệ, phiên bản C có thể tăng InvalidOperation nếu toán hạng thứ hai không thể được chuyển đổi chính xác.

exp(context=None)

Trả về giá trị của hàm mũ (tự nhiên) e**x tại số đã cho. Kết quả được làm tròn chính xác bằng chế độ làm tròn ROUND_HALF_EVEN.

>>> Decimal(1).exp()
Decimal('2.718281828459045235360287471')
>>> Decimal(321).exp()
Decimal('2.561702493119680037517373933E+139')
classmethod from_float(f, /)

Hàm tạo thay thế chỉ chấp nhận các phiên bản của float hoặc int.

Lưu ý Decimal.from_float(0.1) không giống Decimal('0.1'). Vì 0,1 không thể biểu thị chính xác trong dấu phẩy động nhị phân nên giá trị được lưu trữ dưới dạng giá trị biểu thị gần nhất là 0x1.999999999999ap-4. Giá trị tương đương đó ở dạng thập phân là 0.1000000000000000055511151231257827021181583404541015625.

Ghi chú

Từ Python 3.2 trở đi, phiên bản Decimal cũng có thể được tạo trực tiếp từ float.

>>> Thập phân.from_float(0.1)
Thập phân('0.10000000000000000055511151231257827021181583404541015625')
>>> Decimal.from_float(float('nan'))
Thập phân('NaN')
>>> Decimal.from_float(float('inf'))
Thập phân('Vô cực')
>>> Decimal.from_float(float('-inf'))
Thập phân('-Infinity')

Added in version 3.1.

classmethod from_number(number, /)

Hàm tạo thay thế chỉ chấp nhận các phiên bản của float, int hoặc Decimal chứ không chấp nhận chuỗi hoặc bộ dữ liệu.

>>> Số thập phân.from_number(314)
Thập phân('314')
>>> Số thập phân.from_number(0.1)
Thập phân('0.10000000000000000055511151231257827021181583404541015625')
>>> Số thập phân.from_number(Số thập phân('3.14'))
Thập phân('3.14')

Added in version 3.14.

fma(other, third, context=None)

Hợp nhất nhân-cộng. Trở về self*other+third with no rounding of the intermediate product self*other.

>>> Decimal(2).fma(3, 5)
Decimal('11')
is_canonical()

Trả về True nếu đối số là chuẩn và False nếu ngược lại. Hiện tại, phiên bản Decimal luôn là phiên bản chuẩn, vì vậy thao tác này luôn trả về True.

is_finite()

Trả về True nếu đối số là số hữu hạn và False nếu đối số là vô cùng hoặc NaN.

is_infinite()

Trả về True nếu đối số là vô cực dương hoặc âm và False nếu ngược lại.

is_nan()

Trả về True nếu đối số là NaN (im lặng hoặc báo hiệu) và False nếu ngược lại.

is_normal(context=None)

Trả về True nếu đối số là số hữu hạn normal. Trả về False nếu đối số bằng 0, dưới chuẩn, vô hạn hoặc NaN.

is_qnan()

Trả về True nếu đối số là NaN yên tĩnh và False nếu ngược lại.

is_signed()

Trả về True nếu đối số có dấu âm và False nếu ngược lại. Lưu ý rằng số không và NaN đều có thể mang dấu.

is_snan()

Trả về True nếu đối số là NaN báo hiệu và False nếu ngược lại.

is_subnormal(context=None)

Trả về True nếu đối số không bình thường và False nếu ngược lại.

is_zero()

Trả về True nếu đối số là 0 (dương hoặc âm) và False nếu ngược lại.

ln(context=None)

Trả về logarit tự nhiên (cơ số e) của toán hạng. Kết quả được làm tròn chính xác bằng chế độ làm tròn ROUND_HALF_EVEN.

log10(context=None)

Trả về logarit cơ số mười của toán hạng. Kết quả được làm tròn chính xác bằng chế độ làm tròn ROUND_HALF_EVEN.

logb(context=None)

Đối với số khác 0, trả về số mũ đã điều chỉnh của toán hạng của nó dưới dạng phiên bản Decimal. Nếu toán hạng bằng 0 thì Decimal('-Infinity') được trả về và cờ DivisionByZero được nâng lên. Nếu toán hạng là vô cùng thì trả về Decimal('Infinity').

logical_and(other, context=None)

logical_and() là một phép toán logic cần hai logical operands (xem Toán hạng logic). Kết quả là and theo chữ số của hai toán hạng.

logical_invert(context=None)

logical_invert() là một hoạt động hợp lý. Kết quả là sự đảo ngược chữ số của toán hạng.

logical_or(other, context=None)

logical_or() là một phép toán logic cần hai logical operands (xem Toán hạng logic). Kết quả là or theo chữ số của hai toán hạng.

logical_xor(other, context=None)

logical_xor() là một phép toán logic cần hai logical operands (xem Toán hạng logic). Kết quả là loại trừ chữ số hoặc của hai toán hạng.

max(other, context=None)

Giống như max(self, other) ngoại trừ quy tắc làm tròn ngữ cảnh được áp dụng trước khi trả về và các giá trị NaN được báo hiệu hoặc bị bỏ qua (tùy thuộc vào ngữ cảnh và chúng đang báo hiệu hay im lặng).

max_mag(other, context=None)

Tương tự như phương pháp max(), nhưng việc so sánh được thực hiện bằng cách sử dụng các giá trị tuyệt đối của toán hạng.

min(other, context=None)

Giống như min(self, other) ngoại trừ quy tắc làm tròn ngữ cảnh được áp dụng trước khi trả về và các giá trị NaN được báo hiệu hoặc bị bỏ qua (tùy thuộc vào ngữ cảnh và chúng đang báo hiệu hay im lặng).

min_mag(other, context=None)

Tương tự như phương pháp min(), nhưng việc so sánh được thực hiện bằng cách sử dụng các giá trị tuyệt đối của toán hạng.

next_minus(context=None)

Trả về số lớn nhất có thể biểu thị trong ngữ cảnh đã cho (hoặc trong ngữ cảnh của luồng hiện tại nếu không có ngữ cảnh nào được đưa ra) nhỏ hơn toán hạng đã cho.

next_plus(context=None)

Trả về số nhỏ nhất có thể biểu thị trong ngữ cảnh đã cho (hoặc trong ngữ cảnh của luồng hiện tại nếu không có ngữ cảnh nào được đưa ra) lớn hơn toán hạng đã cho.

next_toward(other, context=None)

Nếu hai toán hạng không bằng nhau, hãy trả về số gần nhất với toán hạng thứ nhất theo hướng của toán hạng thứ hai. Nếu cả hai toán hạng đều bằng nhau về số lượng, hãy trả về một bản sao của toán hạng đầu tiên với dấu được đặt giống với dấu của toán hạng thứ hai.

normalize(context=None)

Được sử dụng để tạo ra các giá trị chuẩn của lớp tương đương trong ngữ cảnh hiện tại hoặc ngữ cảnh được chỉ định.

Điều này có cùng ngữ nghĩa với phép toán cộng một ngôi, ngoại trừ việc nếu kết quả cuối cùng là hữu hạn thì nó được rút gọn về dạng đơn giản nhất, với tất cả các số 0 ở cuối bị loại bỏ và dấu của nó được giữ nguyên. Nghĩa là, trong khi hệ số khác 0 và bội số của 10 thì hệ số được chia cho 10 và số mũ được tăng thêm 1. Ngược lại (hệ số bằng 0) thì số mũ được đặt thành 0. Trong mọi trường hợp, dấu không thay đổi.

Ví dụ: Decimal('32.100')Decimal('0.321000e+2') đều chuẩn hóa thành giá trị tương đương Decimal('32.1').

Lưu ý rằng làm tròn được áp dụng before giảm xuống dạng đơn giản nhất.

Trong các phiên bản mới nhất của thông số kỹ thuật, thao tác này còn được gọi là reduce.

number_class(context=None)

Trả về một chuỗi mô tả class của toán hạng. Giá trị trả về là một trong mười chuỗi sau.

  • "-Infinity", chỉ ra rằng toán hạng là âm vô cùng.

  • "-Normal", cho biết toán hạng là số bình thường âm.

  • "-Subnormal", chỉ ra rằng toán hạng là âm và không bình thường.

  • "-Zero", cho biết toán hạng là số 0 âm.

  • "+Zero", cho biết toán hạng là số 0 dương.

  • "+Subnormal", cho biết toán hạng là dương và không bình thường.

  • "+Normal", cho biết toán hạng là số bình thường dương.

  • "+Infinity", biểu thị rằng toán hạng là dương vô cùng.

  • "NaN", cho biết toán hạng là NaN yên tĩnh (Không phải số).

  • "sNaN", chỉ ra rằng toán hạng là NaN báo hiệu.

quantize(exp, rounding=None, context=None)

Trả về giá trị bằng toán hạng thứ nhất sau khi làm tròn và có số mũ của toán hạng thứ hai.

>>> Decimal('1.41421356').quantize(Decimal('1.000'))
Decimal('1.414')

Không giống như các phép toán khác, nếu độ dài của hệ số sau phép toán lượng tử hóa lớn hơn độ chính xác thì InvalidOperation sẽ được báo hiệu. Điều này đảm bảo rằng, trừ khi có điều kiện lỗi, số mũ lượng tử hóa luôn bằng toán hạng bên phải.

Ngoài ra, không giống như các hoạt động khác, lượng tử hóa không bao giờ báo hiệu Underflow, ngay cả khi kết quả dưới mức bình thường và không chính xác.

Nếu số mũ của toán hạng thứ hai lớn hơn số mũ của toán hạng thứ nhất thì có thể cần phải làm tròn. Trong trường hợp này, chế độ làm tròn được xác định bởi đối số rounding nếu được đưa ra, nếu không thì bằng đối số context đã cho; nếu không có đối số nào được đưa ra thì chế độ làm tròn của ngữ cảnh của luồng hiện tại sẽ được sử dụng.

Một lỗi được trả về bất cứ khi nào số mũ kết quả lớn hơn Emax hoặc nhỏ hơn Etiny().

radix()

Trả về Decimal(10), cơ số (cơ số) trong đó lớp Decimal thực hiện tất cả số học của nó. Bao gồm để tương thích với đặc điểm kỹ thuật.

remainder_near(other, context=None)

Trả về số dư khi chia self cho other. Điều này khác với self % other ở chỗ dấu của phần dư được chọn để cực tiểu hóa giá trị tuyệt đối của nó. Chính xác hơn, giá trị trả về là self - n * other trong đó n là số nguyên gần nhất với giá trị chính xác của self / other và nếu hai số nguyên gần bằng nhau thì số chẵn sẽ được chọn.

Nếu kết quả bằng 0 thì dấu của nó sẽ là dấu của self.

>>> Decimal(18).remainder_near(Decimal(10))
Decimal('-2')
>>> Decimal(25).remainder_near(Decimal(10))
Decimal('5')
>>> Decimal(35).remainder_near(Decimal(10))
Decimal('-5')
rotate(other, context=None)

Trả về kết quả của việc xoay các chữ số của toán hạng thứ nhất theo số lượng được chỉ định bởi toán hạng thứ hai. Toán hạng thứ hai phải là số nguyên trong phạm vi - độ chính xác đến độ chính xác. Giá trị tuyệt đối của toán hạng thứ hai cho biết số vị trí cần xoay. Nếu toán hạng thứ hai là dương thì phép quay sang trái; nếu không thì xoay sang phải. Hệ số của toán hạng đầu tiên được đệm ở bên trái với độ chính xác từ 0 đến độ dài nếu cần. Dấu và số mũ của toán hạng đầu tiên không thay đổi.

same_quantum(other, context=None)

Kiểm tra xem bản thân và người khác có cùng số mũ hay cả hai đều là NaN.

Hoạt động này không bị ảnh hưởng bởi bối cảnh và yên tĩnh: không có cờ nào được thay đổi và không thực hiện làm tròn. Là một ngoại lệ, phiên bản C có thể tăng InvalidOperation nếu toán hạng thứ hai không thể được chuyển đổi chính xác.

scaleb(other, context=None)

Trả về toán hạng đầu tiên với số mũ được điều chỉnh theo số thứ hai. Tương tự, trả về toán hạng đầu tiên nhân với 10**other. Toán hạng thứ hai phải là số nguyên.

shift(other, context=None)

Trả về kết quả của việc dịch chuyển các chữ số của toán hạng thứ nhất theo số lượng được chỉ định bởi toán hạng thứ hai. Toán hạng thứ hai phải là số nguyên trong phạm vi - độ chính xác đến độ chính xác. Giá trị tuyệt đối của toán hạng thứ hai cho biết số vị trí cần dịch chuyển. Nếu toán hạng thứ hai dương thì phép dịch sang trái; nếu không thì sự dịch chuyển sang phải. Các chữ số được chuyển vào hệ số là số không. Dấu và số mũ của toán hạng đầu tiên không thay đổi.

sqrt(context=None)

Trả lại căn bậc hai của đối số về độ chính xác hoàn toàn.

to_eng_string(context=None)

Chuyển đổi thành chuỗi, sử dụng ký hiệu kỹ thuật nếu cần số mũ.

Ký hiệu kỹ thuật có số mũ là bội số của 3. Ký hiệu này có thể để lại tối đa 3 chữ số ở bên trái vị trí thập phân và có thể yêu cầu thêm một hoặc hai số 0 ở cuối.

Ví dụ: điều này chuyển đổi Decimal('123E+1') thành Decimal('1.23E+3').

to_integral(rounding=None, context=None)

Giống hệt với phương pháp to_integral_value(). Tên to_integral đã được giữ lại để tương thích với các phiên bản cũ hơn.

to_integral_exact(rounding=None, context=None)

Làm tròn đến số nguyên gần nhất, báo hiệu Inexact hoặc Rounded nếu thích hợp nếu làm tròn. Chế độ làm tròn được xác định bởi tham số rounding nếu được cung cấp, nếu không thì được xác định bởi context đã cho. Nếu không có tham số nào được đưa ra thì chế độ làm tròn của ngữ cảnh hiện tại sẽ được sử dụng.

to_integral_value(rounding=None, context=None)

Làm tròn đến số nguyên gần nhất mà không báo hiệu Inexact hoặc Rounded. Nếu được, áp dụng rounding; mặt khác, sử dụng phương pháp làm tròn trong context được cung cấp hoặc ngữ cảnh hiện tại.

Số thập phân có thể được làm tròn bằng hàm round():

round(number)
round(number, ndigits)

Nếu ndigits không được cung cấp hoặc None, trả về int gần nhất cho number, làm tròn các mối quan hệ thành chẵn và bỏ qua chế độ làm tròn của ngữ cảnh Decimal. Tăng OverflowError nếu number là vô cực hoặc ValueError nếu nó là NaN (im lặng hoặc báo hiệu).

Nếu ndigitsint, chế độ làm tròn ngữ cảnh sẽ được tôn trọng và trả về Decimal đại diện cho number được làm tròn đến bội số gần nhất của Decimal('1E-ndigits'); trong trường hợp này, round(number, ndigits) tương đương với self.quantize(Decimal('1E-ndigits')). Trả về Decimal('NaN') nếu number là NaN yên tĩnh. Tăng InvalidOperation nếu number là vô cực, NaN báo hiệu hoặc nếu độ dài của hệ số sau thao tác lượng tử hóa sẽ lớn hơn độ chính xác của ngữ cảnh hiện tại. Nói cách khác, đối với các trường hợp không góc:

  • nếu ndigits là dương, trả về number được làm tròn đến số thập phân ndigits;

  • nếu ndigits bằng 0, trả về number được làm tròn đến số nguyên gần nhất;

  • nếu ndigits âm, trả về number được làm tròn đến bội số gần nhất của 10**abs(ndigits).

Ví dụ:

>>> từ nhập thập phân Thập phân, getcontext, ROUND_DOWN
>>> getcontext().rounding = ROUND_DOWN
>>> round(Decimal('3.75')) làm tròn # context bị bỏ qua
4
>>> tròn(Thập phân('3.5')) # round-ties-to-even
4
>>> round(Decimal('3.75'), 0) # uses làm tròn bối cảnh
Thập phân('3')
>>> vòng(Thập phân('3.75'), 1)
Thập phân('3.7')
>>> vòng(Thập phân('3.75'), -1)
Thập phân('0E+1')

Toán hạng logic

Các phương thức logical_and(), logical_invert(), logical_or()logical_xor() dự kiến đối số của chúng là logical operands. logical operand là một phiên bản Decimal có số mũ và dấu đều bằng 0 và các chữ số của nó đều là 0 hoặc 1.

Đối tượng bối cảnh

Bối cảnh là môi trường cho các phép tính số học. Chúng chi phối độ chính xác, đặt ra các quy tắc làm tròn, xác định tín hiệu nào được coi là ngoại lệ và giới hạn phạm vi cho số mũ.

Mỗi luồng có bối cảnh hiện tại riêng được truy cập hoặc thay đổi bằng cách sử dụng các hàm getcontext()setcontext():

decimal.getcontext()

Trả về bối cảnh hiện tại cho chuỗi hoạt động.

decimal.setcontext(c, /)

Đặt bối cảnh hiện tại cho chuỗi hoạt động thành c.

Bạn cũng có thể sử dụng câu lệnh with và hàm localcontext() để tạm thời thay đổi ngữ cảnh hoạt động.

decimal.localcontext(ctx=None, **kwargs)

Trả về trình quản lý bối cảnh sẽ đặt bối cảnh hiện tại cho luồng đang hoạt động thành bản sao của ctx khi nhập câu lệnh with và khôi phục ngữ cảnh trước đó khi thoát câu lệnh with. Nếu không có ngữ cảnh nào được chỉ định thì bản sao của ngữ cảnh hiện tại sẽ được sử dụng. Đối số kwargs được sử dụng để đặt thuộc tính của bối cảnh mới.

Ví dụ: đoạn mã sau đặt độ chính xác thập phân hiện tại thành 42 vị trí, thực hiện phép tính rồi tự động khôi phục ngữ cảnh trước đó:

từ bối cảnh cục bộ nhập thập phân

với localcontext()  ctx:
    ctx.prec = 42 # Perform một phép tính có độ chính xác cao
    s = tính_thứ  đó()
s = +s # Round kết quả cuối cùng trở về độ chính xác mặc định

Sử dụng đối số từ khóa, mã sẽ như sau:

từ bối cảnh cục bộ nhập thập phân

với localcontext(prec=42)  ctx:
    s = tính_thứ  đó()
s = +s

Tăng TypeError nếu kwargs cung cấp thuộc tính mà Context không hỗ trợ. Tăng TypeError hoặc ValueError nếu kwargs cung cấp giá trị không hợp lệ cho một thuộc tính.

Thay đổi trong phiên bản 3.11: localcontext() hiện hỗ trợ cài đặt thuộc tính ngữ cảnh thông qua việc sử dụng đối số từ khóa.

decimal.IEEEContext(bits)

Trả về một đối tượng bối cảnh được khởi tạo về các giá trị thích hợp cho một trong các định dạng trao đổi IEEE. Đối số phải là bội số của 32 và nhỏ hơn IEEE_CONTEXT_MAX_BITS.

Added in version 3.14.

Các bối cảnh mới cũng có thể được tạo bằng cách sử dụng hàm tạo Context được mô tả bên dưới. Ngoài ra, mô-đun này còn cung cấp ba bối cảnh được tạo sẵn:

decimal.BasicContext

Đây là bối cảnh tiêu chuẩn được xác định bởi Đặc tả số học thập phân chung. Độ chính xác được đặt thành chín. Làm tròn được đặt thành ROUND_HALF_UP. Tất cả các cờ đều bị xóa. Tất cả các bẫy đều được bật (được coi là ngoại lệ) ngoại trừ Inexact, RoundedSubnormal.

Bởi vì nhiều bẫy được kích hoạt nên bối cảnh này rất hữu ích cho việc gỡ lỗi.

decimal.ExtendedContext

Đây là bối cảnh tiêu chuẩn được xác định bởi Đặc tả số học thập phân chung. Độ chính xác được đặt thành chín. Làm tròn được đặt thành ROUND_HALF_EVEN. Tất cả các cờ đều bị xóa. Không có bẫy nào được kích hoạt (để các ngoại lệ không xuất hiện trong quá trình tính toán).

Vì bẫy bị vô hiệu hóa nên ngữ cảnh này hữu ích cho các ứng dụng muốn có giá trị kết quả là NaN hoặc Infinity thay vì đưa ra các ngoại lệ. Điều này cho phép ứng dụng hoàn tất quá trình chạy khi có các điều kiện có thể khiến chương trình bị dừng.

decimal.DefaultContext

Ngữ cảnh này được hàm tạo Context sử dụng làm nguyên mẫu cho các ngữ cảnh mới. Việc thay đổi một trường (độ chính xác như vậy) có tác dụng thay đổi mặc định cho các ngữ cảnh mới được tạo bởi hàm tạo Context.

Ngữ cảnh này hữu ích nhất trong môi trường đa luồng. Việc thay đổi một trong các trường trước khi bắt đầu luồng có tác dụng đặt mặc định trên toàn hệ thống. Không nên thay đổi các trường sau khi các luồng đã bắt đầu vì nó sẽ yêu cầu đồng bộ hóa luồng để ngăn chặn tình trạng chạy đua.

Trong môi trường đơn luồng, tốt nhất là không sử dụng ngữ cảnh này. Thay vào đó, chỉ cần tạo ngữ cảnh một cách rõ ràng như được mô tả bên dưới.

Các giá trị mặc định là Context.prec=28, Context.rounding=ROUND_HALF_EVEN và bật bẫy cho Overflow, InvalidOperationDivisionByZero.

Ngoài ba ngữ cảnh được cung cấp, các ngữ cảnh mới có thể được tạo bằng hàm tạo Context.

class decimal.Context(prec=None, rounding=None, Emin=None, Emax=None, capitals=None, clamp=None, flags=None, traps=None)

Tạo ra một bối cảnh mới. Nếu một trường không được chỉ định hoặc là None, thì các giá trị mặc định sẽ được sao chép từ DefaultContext. Nếu trường flags không được chỉ định hoặc là None, tất cả các cờ sẽ bị xóa.

prec

Một số nguyên trong phạm vi [1, MAX_PREC] đặt độ chính xác cho các phép tính số học trong ngữ cảnh.

rounding

Một trong các hằng số được liệt kê trong phần Rounding Modes.

traps
flags

Danh sách bất kỳ tín hiệu nào sẽ được thiết lập. Nói chung, bối cảnh mới chỉ nên đặt bẫy và bỏ cờ rõ ràng.

Emin
Emax

Số nguyên xác định giới hạn bên ngoài cho phép đối với số mũ. Emin phải nằm trong phạm vi [MIN_EMIN, 0], Emax trong phạm vi [0, MAX_EMAX].

capitals

0 hoặc 1 (mặc định). Nếu được đặt thành 1, số mũ được in bằng chữ hoa E; nếu không, e viết thường sẽ được sử dụng: Decimal('6.02e+23').

clamp

0 (mặc định) hoặc 1. Nếu được đặt thành 1, số mũ e của phiên bản Decimal có thể biểu thị trong ngữ cảnh này bị giới hạn nghiêm ngặt trong phạm vi Emin - prec + 1 <= e <= Emax - prec + 1. Nếu clamp0 thì điều kiện yếu hơn được giữ nguyên: số mũ được điều chỉnh của phiên bản Decimal nhiều nhất là Emax. Khi clamp1, một số bình thường lớn, nếu có thể, sẽ có số mũ giảm đi và một số số 0 tương ứng được thêm vào hệ số của nó, để phù hợp với các ràng buộc số mũ; điều này bảo toàn giá trị của số nhưng làm mất thông tin về các số 0 ở cuối có ý nghĩa. Ví dụ:

>>> Ngữ cảnh(prec=6, Emax=999, kẹp=1).create_decimal('1.23e999')
Thập phân('1.23000E+999')

Giá trị clamp của 1 cho phép tương thích với các định dạng trao đổi thập phân có chiều rộng cố định được chỉ định trong IEEE 754.

Lớp Context định nghĩa một số phương thức có mục đích chung cũng như một số lượng lớn các phương thức để thực hiện số học trực tiếp trong một ngữ cảnh nhất định. Ngoài ra, đối với mỗi phương thức Decimal được mô tả ở trên (ngoại trừ phương thức adjusted()as_tuple()) đều có một phương thức Context tương ứng. Ví dụ: đối với phiên bản Context CDecimal x, C.exp(x) tương đương với x.exp(context=C). Mỗi phương thức Context chấp nhận một số nguyên Python (một phiên bản của int) ở bất kỳ nơi nào mà phiên bản thập phân được chấp nhận.

clear_flags()

Đặt lại tất cả các cờ thành 0.

clear_traps()

Đặt lại tất cả các bẫy về 0.

Added in version 3.3.

copy()

Trả về một bản sao của bối cảnh.

copy_decimal(num, /)

Trả về một bản sao của số thập phân.

create_decimal(num='0', /)

Tạo một phiên bản thập phân mới từ num nhưng sử dụng self làm ngữ cảnh. Không giống như hàm tạo Decimal, độ chính xác của ngữ cảnh, phương pháp làm tròn, cờ và bẫy được áp dụng cho chuyển đổi.

Điều này rất hữu ích vì các hằng số thường được cung cấp với độ chính xác cao hơn mức cần thiết của ứng dụng. Một lợi ích khác là việc làm tròn ngay lập tức loại bỏ các tác động không mong muốn từ các chữ số vượt quá độ chính xác hiện tại. Trong ví dụ sau, việc sử dụng đầu vào không làm tròn có nghĩa là việc thêm 0 vào tổng có thể thay đổi kết quả:

>>> getcontext().prec = 3
>>> Số thập phân('3.4445') + Số thập phân('1.0023')
Thập phân('4.45')
>>> Số thập phân('3.4445') + Số thập phân(0) + Số thập phân('1.0023')
Thập phân('4.44')

Phương thức này triển khai hoạt động theo số của đặc tả IBM. Nếu đối số là một chuỗi thì không được phép có khoảng trắng ở đầu hoặc cuối hoặc dấu gạch dưới.

create_decimal_from_float(f, /)

Tạo một phiên bản thập phân mới từ float f nhưng làm tròn bằng cách sử dụng self làm ngữ cảnh. Không giống như phương thức lớp Decimal.from_float(), độ chính xác của ngữ cảnh, phương thức làm tròn, cờ và bẫy được áp dụng cho chuyển đổi.

>>> bối cảnh = Bối cảnh(prec=5, làm tròn=ROUND_DOWN)
>>> context.create_decimal_from_float(math.pi)
Thập phân('3.1415')
>>> bối cảnh = Bối cảnh(prec=5, bẫy=[Không chính xác])
>>> context.create_decimal_from_float(math.pi)
Traceback (cuộc gọi gần đây nhất):
    ...
thập phân.Không chính xác: Không có

Added in version 3.1.

Etiny()

Trả về giá trị bằng Emin - prec + 1, giá trị số mũ tối thiểu cho các kết quả không bình thường. Khi xảy ra hiện tượng tràn, số mũ được đặt thành Etiny.

Etop()

Trả về giá trị bằng Emax - prec + 1.

Cách tiếp cận thông thường để làm việc với số thập phân là tạo các phiên bản Decimal và sau đó áp dụng các phép toán số học diễn ra trong ngữ cảnh hiện tại cho luồng đang hoạt động. Một cách tiếp cận khác là sử dụng các phương pháp ngữ cảnh để tính toán trong một ngữ cảnh cụ thể. Các phương thức này tương tự như các phương thức của lớp Decimal và chỉ được kể lại ngắn gọn ở đây.

abs(x, /)

Trả về giá trị tuyệt đối của x.

add(x, y, /)

Trả về tổng của xy.

canonical(x, /)

Trả về cùng một đối tượng thập phân x.

compare(x, y, /)

So sánh xy bằng số.

compare_signal(x, y, /)

So sánh các giá trị của hai toán hạng bằng số.

compare_total(x, y, /)

So sánh hai toán hạng bằng cách sử dụng biểu diễn trừu tượng của chúng.

compare_total_mag(x, y, /)

So sánh hai toán hạng bằng cách sử dụng biểu diễn trừu tượng của chúng, bỏ qua dấu.

copy_abs(x, /)

Trả về bản sao của x với dấu được đặt thành 0.

copy_negate(x, /)

Trả về một bản sao của x với dấu bị đảo ngược.

copy_sign(x, y, /)

Sao chép dấu hiệu từ y sang x.

divide(x, y, /)

Trả về x chia cho y.

divide_int(x, y, /)

Trả về x chia cho y, cắt ngắn thành số nguyên.

divmod(x, y, /)

Chia hai số và trả về phần nguyên của kết quả.

exp(x, /)

Trả về e ** x.

fma(x, y, z, /)

Trả về x nhân với y, cộng với z.

is_canonical(x, /)

Trả về True nếu x là chuẩn; nếu không thì trả về False.

is_finite(x, /)

Trả về True nếu x hữu hạn; nếu không thì trả về False.

is_infinite(x, /)

Trả về True nếu x là vô hạn; nếu không thì trả về False.

is_nan(x, /)

Trả về True nếu x là qNaN hoặc sNaN; nếu không thì trả về False.

is_normal(x, /)

Trả về True nếu x là số bình thường; nếu không thì trả về False.

is_qnan(x, /)

Trả về True nếu x là NaN yên tĩnh; nếu không thì trả về False.

is_signed(x, /)

Trả về True nếu x âm; nếu không thì trả về False.

is_snan(x, /)

Trả về True nếu x là NaN báo hiệu; nếu không thì trả về False.

is_subnormal(x, /)

Trả về True nếu x không bình thường; nếu không thì trả về False.

is_zero(x, /)

Trả về True nếu x bằng 0; nếu không thì trả về False.

ln(x, /)

Trả về logarit tự nhiên (cơ số e) của x.

log10(x, /)

Trả về logarit cơ số 10 của x.

logb(x, /)

Trả về số mũ của độ lớn MSD của toán hạng.

logical_and(x, y, /)

Áp dụng phép toán logic and giữa các chữ số của mỗi toán hạng.

logical_invert(x, /)

Đảo ngược tất cả các chữ số trong x.

logical_or(x, y, /)

Áp dụng phép toán logic or giữa các chữ số của mỗi toán hạng.

logical_xor(x, y, /)

Áp dụng phép toán logic xor giữa các chữ số của mỗi toán hạng.

max(x, y, /)

So sánh hai giá trị bằng số và trả về giá trị lớn nhất.

max_mag(x, y, /)

So sánh các giá trị bằng số với dấu của chúng bị bỏ qua.

min(x, y, /)

So sánh hai giá trị bằng số và trả về giá trị tối thiểu.

min_mag(x, y, /)

So sánh các giá trị bằng số với dấu của chúng bị bỏ qua.

minus(x, /)

Dấu trừ tương ứng với toán tử trừ tiền tố đơn nhất trong Python.

multiply(x, y, /)

Trả lại sản phẩm của xy.

next_minus(x, /)

Trả về số đại diện lớn nhất nhỏ hơn x.

next_plus(x, /)

Trả về số có thể biểu thị nhỏ nhất lớn hơn x.

next_toward(x, y, /)

Trả về số gần nhất với x, hướng về y.

normalize(x, /)

Giảm x về dạng đơn giản nhất.

number_class(x, /)

Trả về một dấu hiệu của lớp x.

plus(x, /)

Plus tương ứng với toán tử cộng tiền tố đơn nhất trong Python. Thao tác này áp dụng độ chính xác của ngữ cảnh và làm tròn, do đó, đây là thao tác nhận dạng not.

power(x, y, modulo=None)

Trả x về sức mạnh của y, giảm modulo modulo nếu được.

Với hai đối số, hãy tính x**y. Nếu x âm thì y phải là tích phân. Kết quả sẽ không chính xác trừ khi y là tích phân và kết quả là hữu hạn và có thể được biểu thị chính xác bằng các chữ số 'chính xác'. Chế độ làm tròn ngữ cảnh được sử dụng. Kết quả luôn được làm tròn chính xác trong phiên bản Python.

Decimal(0) ** Decimal(0) dẫn đến InvalidOperation và nếu InvalidOperation không bị mắc kẹt thì sẽ tạo ra Decimal('NaN').

Thay đổi trong phiên bản 3.3: Mô-đun C tính toán power() theo các hàm exp()ln() được làm tròn chính xác. Kết quả được xác định rõ ràng nhưng chỉ "hầu như luôn được làm tròn chính xác".

Với ba đối số, hãy tính (x**y) % modulo. Đối với dạng ba đối số, các hạn chế sau đây đối với các đối số được giữ nguyên:

  • cả ba đối số phải tích phân

  • y phải không âm

  • ít nhất một trong số x hoặc y phải khác 0

  • modulo phải khác 0 và có tối đa các chữ số 'chính xác'

Giá trị thu được từ Context.power(x, y, modulo) bằng với giá trị thu được bằng cách tính toán (x**y) % modulo với độ chính xác không giới hạn, nhưng được tính toán hiệu quả hơn. Số mũ của kết quả bằng 0, bất kể số mũ của x, ymodulo. Kết quả luôn chính xác.

quantize(x, y, /)

Trả về giá trị bằng x (làm tròn), có số mũ là y.

radix()

Chỉ trả về 10, vì đây là Số thập phân, :)

remainder(x, y, /)

Trả về phần còn lại từ phép chia số nguyên.

Dấu của kết quả, nếu khác 0, giống với dấu của số bị chia ban đầu.

remainder_near(x, y, /)

Trả về x - y * n, trong đó n là số nguyên gần nhất với giá trị chính xác của x / y (nếu kết quả là 0 thì dấu của nó sẽ là dấu của x).

rotate(x, y, /)

Trả về bản sao được xoay của x, y lần.

same_quantum(x, y, /)

Trả về True nếu hai toán hạng có cùng số mũ.

scaleb(x, y, /)

Trả về toán hạng đầu tiên sau khi cộng giá trị thứ hai exp của nó.

shift(x, y, /)

Trả về bản sao đã dịch chuyển của x, y lần.

sqrt(x, /)

Căn bậc hai của số không âm theo độ chính xác của ngữ cảnh.

subtract(x, y, /)

Trả về sự khác biệt giữa xy.

to_eng_string(x, /)

Chuyển đổi thành chuỗi, sử dụng ký hiệu kỹ thuật nếu cần số mũ.

Ký hiệu kỹ thuật có số mũ là bội số của 3. Ký hiệu này có thể để lại tối đa 3 chữ số ở bên trái vị trí thập phân và có thể yêu cầu thêm một hoặc hai số 0 ở cuối.

to_integral_exact(x, /)

Làm tròn thành một số nguyên.

to_sci_string(x, /)

Chuyển đổi một số thành một chuỗi bằng ký hiệu khoa học.

Hằng số

Các hằng số trong phần này chỉ liên quan đến mô-đun C. Chúng cũng được bao gồm trong phiên bản Python thuần túy để tương thích.

32-bit

64-bit

decimal.MAX_PREC

425000000

999999999999999999

decimal.MAX_EMAX

425000000

999999999999999999

decimal.MIN_EMIN

-425000000

-999999999999999999

decimal.MIN_ETINY

-849999999

-1999999999999999997

decimal.IEEE_CONTEXT_MAX_BITS

256

512

decimal.HAVE_THREADS

Giá trị là True. Không được dùng nữa vì Python hiện luôn có các luồng.

Sắp loại bỏ từ phiên bản 3.9.

decimal.HAVE_CONTEXTVAR

Giá trị mặc định là True. Nếu Python là configured using the --without-decimal-contextvar option thì phiên bản C sử dụng ngữ cảnh luồng cục bộ thay vì ngữ cảnh coroutine cục bộ và giá trị là False. Điều này nhanh hơn một chút trong một số trường hợp ngữ cảnh lồng nhau.

Added in version 3.8.3.

Chế độ làm tròn

decimal.ROUND_CEILING

Vòng về phía Infinity.

decimal.ROUND_DOWN

Làm tròn về số không.

decimal.ROUND_FLOOR

Vòng về phía -Infinity.

decimal.ROUND_HALF_DOWN

Làm tròn đến gần nhất với các mối quan hệ tiến về 0.

decimal.ROUND_HALF_EVEN

Làm tròn đến gần nhất với các mối quan hệ sẽ tiến đến số nguyên chẵn gần nhất.

decimal.ROUND_HALF_UP

Làm tròn đến gần nhất với các mối quan hệ cách xa số 0.

decimal.ROUND_UP

Làm tròn từ số 0.

decimal.ROUND_05UP

Làm tròn từ 0 nếu chữ số cuối cùng sau khi làm tròn về 0 sẽ là 0 hoặc 5; nếu không thì làm tròn về 0.

Tín hiệu

Tín hiệu đại diện cho các điều kiện phát sinh trong quá trình tính toán. Mỗi cái tương ứng với một cờ ngữ cảnh và một trình kích hoạt bẫy ngữ cảnh.

Cờ ngữ cảnh được đặt bất cứ khi nào gặp phải điều kiện. Sau khi tính toán, các cờ có thể được kiểm tra nhằm mục đích cung cấp thông tin (ví dụ: để xác định xem tính toán có chính xác hay không). Sau khi kiểm tra các cờ, hãy nhớ xóa tất cả các cờ trước khi bắt đầu tính toán tiếp theo.

Nếu trình kích hoạt bẫy của ngữ cảnh được đặt cho tín hiệu thì điều kiện sẽ khiến ngoại lệ Python được nâng lên. Ví dụ: nếu bẫy DivisionByZero được đặt thì ngoại lệ DivisionByZero sẽ xuất hiện khi gặp phải điều kiện này.

class decimal.Clamped

Đã thay đổi số mũ để phù hợp với các ràng buộc về biểu diễn.

Thông thường, việc kẹp xảy ra khi số mũ nằm ngoài giới hạn EminEmax của ngữ cảnh. Nếu có thể, số mũ được giảm cho phù hợp bằng cách thêm các số 0 vào hệ số.

class decimal.DecimalException

Lớp cơ sở cho các tín hiệu khác và lớp con của ArithmeticError.

class decimal.DivisionByZero

Báo hiệu sự chia một số không vô hạn cho 0.

Có thể xảy ra với phép chia, phép chia modulo hoặc khi nâng một số lên lũy thừa âm. Nếu tín hiệu này không bị giữ lại, trả về Infinity hoặc -Infinity với dấu được xác định bởi đầu vào của phép tính.

class decimal.Inexact

Cho biết rằng việc làm tròn đã xảy ra và kết quả không chính xác.

Tín hiệu khi các chữ số khác 0 bị loại bỏ trong quá trình làm tròn. Kết quả làm tròn được trả về. Cờ tín hiệu hoặc bẫy được sử dụng để phát hiện khi kết quả không chính xác.

class decimal.InvalidOperation

Một thao tác không hợp lệ đã được thực hiện.

Cho biết rằng một thao tác được yêu cầu không có ý nghĩa. Nếu không bị mắc kẹt, trả về NaN. Các nguyên nhân có thể bao gồm:

 Cực -  Cực
0 *  cực
 cực /  cực
x % 0
 cực % x
sqrt(-x)  x > 0
0 ** 0
x ** (không nguyên)
x **  cực
class decimal.Overflow

Tràn số.

Cho biết số mũ lớn hơn Context.Emax sau khi làm tròn số. Nếu không bị mắc kẹt, kết quả sẽ phụ thuộc vào chế độ làm tròn, hoặc kéo vào trong số hữu hạn có thể biểu thị lớn nhất hoặc làm tròn ra ngoài thành Infinity. Trong cả hai trường hợp, InexactRounded cũng được báo hiệu.

class decimal.Rounded

Việc làm tròn đã xảy ra mặc dù có thể không có thông tin nào bị mất.

Được báo hiệu bất cứ khi nào làm tròn loại bỏ các chữ số; ngay cả khi các chữ số đó bằng 0 (chẳng hạn như làm tròn 5.00 thành 5.0). Nếu không bị mắc kẹt, trả về kết quả không thay đổi. Tín hiệu này được sử dụng để phát hiện sự mất chữ số có nghĩa.

class decimal.Subnormal

Số mũ thấp hơn Emin trước khi làm tròn.

Xảy ra khi kết quả phép toán không bình thường (số mũ quá nhỏ). Nếu không bị mắc kẹt, trả về kết quả không thay đổi.

class decimal.Underflow

Tràn dưới dạng số với kết quả được làm tròn về 0.

Xảy ra khi một kết quả không bình thường bị đẩy về 0 bằng cách làm tròn. InexactSubnormal cũng được báo hiệu.

class decimal.FloatOperation

Cho phép ngữ nghĩa chặt chẽ hơn để trộn số float và số thập phân.

Nếu tín hiệu không bị kẹt (mặc định), việc trộn các số float và Số thập phân được cho phép trong hàm tạo Decimal, create_decimal() và tất cả các toán tử so sánh. Cả chuyển đổi và so sánh đều chính xác. Bất kỳ sự xuất hiện nào của một hoạt động hỗn hợp đều được ghi âm thầm bằng cách đặt FloatOperation trong cờ ngữ cảnh. Chuyển đổi rõ ràng bằng from_float() hoặc create_decimal_from_float() không đặt cờ.

Mặt khác (tín hiệu bị kẹt), chỉ so sánh đẳng thức và chuyển đổi rõ ràng là im lặng. Tất cả các hoạt động hỗn hợp khác đều tăng FloatOperation.

Bảng sau đây tóm tắt thứ bậc của tín hiệu:

ngoại lệ.ArithmeticError (ngoại lệ.Exception)
    Ngoại lệ thập phân
        bị kẹp
        DivisionByZero(DecimalException, ngoại lệ.ZeroDivisionError)
        Không chính xác
            Tràn (Không chính xác, Làm tròn)
            Dòng chảy dưới (Không chính xác, Làm tròn, Không bình thường)
        Thao tác không hợp lệ
        làm tròn
        Không bình thường
        FloatOperation(DecimalException, ngoại lệ.TypeError)

Ghi chú dấu phẩy động

Giảm thiểu lỗi làm tròn với độ chính xác cao hơn

Việc sử dụng dấu phẩy động thập phân giúp loại bỏ lỗi biểu diễn thập phân (giúp có thể biểu diễn chính xác 0.1); tuy nhiên, một số thao tác vẫn có thể xảy ra lỗi làm tròn khi các chữ số khác 0 vượt quá độ chính xác cố định.

Tác động của sai số làm tròn có thể được khuếch đại bằng cách cộng hoặc trừ các đại lượng gần bù đắp dẫn đến mất ý nghĩa. Knuth cung cấp hai ví dụ mang tính hướng dẫn trong đó số học dấu phẩy động được làm tròn với độ chính xác không đủ gây ra sự phá vỡ các thuộc tính kết hợp và phân phối của phép cộng:

# Examples từ Thuật toán Seminumerical, Phần 4.2.2.
>>> từ nhập thập phân Thập phân, getcontext
>>> getcontext().prec = 8

>>> u, v, w = Số thập phân(11111113), Số thập phân(-11111111), Số thập phân('7.51111111')
>>> (u + v) + w
Thập phân('9.5111111')
>>> u + (v + w)
Thập phân('10')

>>> u, v, w = Số thập phân(20000), Số thập phân(-6), Số thập phân('6.0000003')
>>> (u*v) + (u*w)
Thập phân('0.01')
>>> u * (v+w)
Thập phân('0.0060000')

Mô-đun decimal cho phép khôi phục danh tính bằng cách mở rộng độ chính xác đủ để tránh mất ý nghĩa:

>>> getcontext().prec = 20
>>> u, v, w = Số thập phân(11111113), Số thập phân(-11111111), Số thập phân('7.51111111')
>>> (u + v) + w
Thập phân('9.51111111')
>>> u + (v + w)
Thập phân('9.51111111')
>>>
>>> u, v, w = Số thập phân(20000), Số thập phân(-6), Số thập phân('6.0000003')
>>> (u*v) + (u*w)
Thập phân('0.0060000')
>>> u * (v+w)
Thập phân('0.0060000')

Giá trị đặc biệt

Hệ thống số cho mô-đun decimal cung cấp các giá trị đặc biệt bao gồm NaN, sNaN, -Infinity, Infinity và hai số 0, +0-0.

Vô cực có thể được xây dựng trực tiếp với: Decimal('Infinity'). Ngoài ra, chúng có thể phát sinh từ việc chia cho 0 khi tín hiệu DivisionByZero không bị kẹt. Tương tự, khi tín hiệu Overflow không bị kẹt, giá trị vô cùng có thể là kết quả của việc làm tròn vượt quá giới hạn của số biểu diễn lớn nhất.

Các số vô hạn được ký (affine) và có thể được sử dụng trong các phép tính số học trong đó chúng được coi là số rất lớn, không xác định. Chẳng hạn, việc thêm một hằng số vào vô cùng sẽ cho một kết quả vô hạn khác.

Một số thao tác không xác định và trả về NaN hoặc nếu tín hiệu InvalidOperation bị kẹt, hãy đưa ra một ngoại lệ. Ví dụ: 0/0 trả về NaN có nghĩa là "không phải số". Loại NaN này hoạt động yên tĩnh và sau khi được tạo, sẽ chuyển qua các tính toán khác và luôn dẫn đến một NaN khác. Hành vi này có thể hữu ích cho một loạt các tính toán đôi khi thiếu đầu vào --- nó cho phép quá trình tính toán tiếp tục trong khi gắn cờ các kết quả cụ thể là không hợp lệ.

Một biến thể là sNaN phát tín hiệu thay vì giữ im lặng sau mỗi hoạt động. Đây là giá trị trả về hữu ích khi một kết quả không hợp lệ cần làm gián đoạn phép tính để xử lý đặc biệt.

Hành vi của các toán tử so sánh của Python có thể hơi ngạc nhiên khi có liên quan đến NaN. Kiểm tra sự bằng nhau trong đó một trong các toán hạng là NaN im lặng hoặc báo hiệu luôn trả về False (ngay cả khi thực hiện Decimal('NaN')==Decimal('NaN')), trong khi kiểm tra bất đẳng thức luôn trả về True. Nỗ lực so sánh hai Số thập phân bằng cách sử dụng bất kỳ toán tử <, <=, > hoặc >= nào sẽ tăng tín hiệu InvalidOperation nếu một trong hai toán hạng là NaN và trả về False nếu tín hiệu này không bị kẹt. Lưu ý rằng đặc tả Số học thập phân tổng quát không chỉ định hành vi so sánh trực tiếp; các quy tắc so sánh liên quan đến NaN này được lấy từ tiêu chuẩn IEEE 854 (xem Bảng 3 trong phần 5.7). Để đảm bảo tuân thủ các tiêu chuẩn nghiêm ngặt, thay vào đó hãy sử dụng các phương pháp compare()compare_signal().

Các số 0 đã ký có thể là kết quả của các phép tính tràn ngập. Họ giữ lại dấu hiệu sẽ có kết quả nếu phép tính được thực hiện với độ chính xác cao hơn. Vì cường độ của chúng bằng 0 nên cả số 0 dương và âm đều được coi là bằng nhau và dấu của chúng mang tính thông tin.

Ngoài hai số 0 có dấu phân biệt nhưng bằng nhau, còn có nhiều cách biểu thị số 0 khác nhau với độ chính xác khác nhau nhưng có giá trị tương đương. Điều này cần một chút để làm quen. Đối với mắt đã quen với các biểu diễn dấu phẩy động được chuẩn hóa, không thể thấy ngay rằng phép tính sau đây trả về giá trị bằng 0:

>>> 1 / Decimal('Infinity')
Decimal('0E-1000026')

Làm việc với chủ đề

Hàm getcontext() truy cập một đối tượng Context khác nhau cho mỗi luồng. Có bối cảnh luồng riêng biệt có nghĩa là các luồng có thể thực hiện thay đổi (chẳng hạn như getcontext().prec=10) mà không can thiệp vào các luồng khác.

Tương tự, hàm setcontext() tự động gán mục tiêu của nó cho luồng hiện tại.

Nếu setcontext() chưa được gọi trước getcontext() thì getcontext() sẽ tự động tạo ngữ cảnh mới để sử dụng trong luồng hiện tại. Các đối tượng bối cảnh mới có các giá trị mặc định được đặt từ đối tượng decimal.DefaultContext.

Cờ sys.flags.thread_inherit_context ảnh hưởng đến ngữ cảnh của các chủ đề mới. Nếu cờ sai, các chủ đề mới sẽ bắt đầu với ngữ cảnh trống. Trong trường hợp này, getcontext() sẽ tạo một đối tượng ngữ cảnh mới khi được gọi và sử dụng các giá trị mặc định từ DefaultContext. Nếu cờ đúng, các chủ đề mới sẽ bắt đầu bằng bản sao ngữ cảnh từ người gọi threading.Thread.start().

Để kiểm soát các giá trị mặc định sao cho mỗi luồng sẽ sử dụng cùng một giá trị trong toàn bộ ứng dụng, hãy sửa đổi trực tiếp đối tượng DefaultContext. Điều này nên được thực hiện before bất kỳ chủ đề nào được bắt đầu để không có tình trạng xung đột giữa các chủ đề gọi getcontext(). Ví dụ:

# Set mặc định trên toàn ứng dụng cho tất cả các chủ đề sắp được khởi chạy
DefaultContext.prec = 12
DefaultContext.rounding = ROUND_DOWN
DefaultContext.traps = ExtendedContext.traps.copy()
DefaultContext.traps[InvalidOperation] = 1
setcontext(DefaultContext)

# Afterwards, các chủ đề có thể được bắt đầu
t1.start()
t2.start()
t3.start()
 . . .

Công thức nấu ăn

Dưới đây là một số công thức đóng vai trò là chức năng tiện ích và minh họa cách làm việc với lớp Decimal:

def moneyfmt(giá trị, địa điểm=2, curr='', sep=',', dp='.',
             pos='', neg='-', Trailneg=''):
    """Chuyển đổi số thập phân thành chuỗi có định dạng tiền.

    vị trí: số vị trí bắt buộc sau dấu thập phân
    Curr: ký hiệu tiền tệ tùy chọn trước dấu (có thể để trống)
    sep: dấu phân cách nhóm tùy chọn (dấu phẩy, dấu chấm, dấu cách hoặc khoảng trống)
    dp: chỉ báo dấu thập phân (dấu phẩy hoặc dấu chấm)
             chỉ chỉ định là trống khi địa điểm bằng 0
    pos: dấu tùy chọn cho số dương: '+', dấu cách hoặc trống
    neg: dấu tùy chọn cho số âm: '-', '(', dấu cách hoặc trống
    dấu vết: chỉ báo dấu trừ ở cuối tùy chọn: '-', ')', dấu cách hoặc để trống

    >>> d = Số thập phân('-1234567.8901')
    >>> moneyfmt(d,curr='$')
    '-$1.234.567,89'
    >>> moneyfmt(d, Places=0, sep='.', dp='', neg='', Trailneg='-')
    '1.234.568-'
    >>> moneyfmt(d,curr='$', neg='(', Trailneg=')')
    '($1.234.567,89)'
    >>> moneyfmt(Thập phân(123456789), sep=' ')
    '123 456 789.00'
    >>> moneyfmt(Thập phân('-0.02'), neg='<', Trailneg='>')
    '<0,02>'

    """
    q = Số thập phân(10) ** -địa điểm # 2 địa điểm --> '0,01'
    dấu, chữ số, exp = value.quantize(q).as_tuple()
    kết quả = []
    chữ số = danh sách (bản đồ (str, chữ số))
    xây dựng, tiếp theo = result.append, chữ số.pop
    dấu nếu:
        xây dựng(trailneg)
    cho tôi trong phạm vi (địa điểm):
        build(next() nếu các chữ số khác '0')
    nếu địa điểm:
        xây dựng (dp)
    nếu không phải  chữ số:
        xây dựng('0')
    tôi = 0
    trong khi chữ số:
        xây dựng(tiếp theo())
        tôi += 1
        nếu i == 3  chữ số:
            tôi = 0
            xây dựng(tháng 9)
    xây dựng (curr)
    build(neg if sign else pos)
    return ''.join(đảo ngược(kết quả))

chắc chắn pi():
    """Tính Pi theo độ chính xác hiện tại.

    >>> in(pi())
    3.141592653589793238462643383

    """
    getcontext().prec += 2 chữ số # extra cho các bước trung gian
    ba = Thập phân(3) # substitute "ba=3.0" cho số float thông thường
    kéo dài, t, s, n, na, d, da = 0, ba, 3, 1, 0, 0, 24
    trong khi s != kéo dài:
        kéo dài = s
        n, na = n+na, na+8
        d, da = d+da, da+32
        t = (t*n)/d
        s += t
    getcontext().prec -= 2
    return +s # unary plus áp dụng độ chính xác mới

def exp(x):
    """Trả về e lũy thừa của x. Loại kết quả khớp với loại đầu vào.

    >>> in(exp(Thập phân(1)))
    2.718281828459045235360287471
    >>> in(exp(Thập phân(2)))
    7.389056098930650227230427461
    >>> in(exp(2.0))
    7.38905609893
    >>> in(exp(2+0j))
    (7.38905609893+0j)

    """
    getcontext().prec += 2
    i, kéo dài, s, thực tế, num = 0, 0, 1, 1, 1
    trong khi s != kéo dài:
        kéo dài = s
        tôi += 1
        sự thật *= tôi
        số *= x
        s += num/sự thật
    getcontext().prec -= 2
    trả lại +s

định nghĩa cos(x):
    """Trả về cosin của x được đo bằng radian.

    Xấp xỉ chuỗi Taylor hoạt động tốt nhất với giá trị x nhỏ.
    Đối với các giá trị lớn hơn, trước tiên hãy tính x = x % (2 * pi).

    >>> in(cos(Thập phân('0.5')))
    0.8775825618903727161162815826
    >>> in(cos(0.5))
    0.87758256189
    >>> in(cos(0.5+0j))
    (0.87758256189+0j)

    """
    getcontext().prec += 2
    i, kéo dài, s, thực tế, num, dấu = 0, 0, 1, 1, 1, 1
    trong khi s != kéo dài:
        kéo dài = s
        tôi += 2
        thực tế *= i * (i-1)
        số *= x * x
         *= -1
        s += num /  hiệu * thực tế
    getcontext().prec -= 2
    trả lại +s

định nghĩa tội lỗi (x):
    """Trả về sin của x được đo bằng radian.

    Xấp xỉ chuỗi Taylor hoạt động tốt nhất với giá trị x nhỏ.
    Đối với các giá trị lớn hơn, trước tiên hãy tính x = x % (2 * pi).

    >>> print(sin(Decimal('0.5')))
    0,4794255386042030002732879352
    >>> in(sin(0.5))
    0.479425538604
    >>> in(sin(0.5+0j))
    (0,479425538604+0j)

    """
    getcontext().prec += 2
    i, kéo dài, s, thực tế, num, dấu = 1, 0, x, 1, x, 1
    trong khi s != kéo dài:
        kéo dài = s
        tôi += 2
        thực tế *= i * (i-1)
        số *= x * x
         *= -1
        s += num /  hiệu * thực tế
    getcontext().prec -= 2
    trả lại +s

FAQ thập phân

Hỏi: Việc gõ decimal.Decimal('1234.5') rất khó khăn. Có cách nào để giảm thiểu việc gõ khi sử dụng trình thông dịch tương tác không?

Đáp: Một số người dùng viết tắt hàm tạo thành chỉ một chữ cái:

>>> D = decimal.Decimal
>>> D('1.23') + D('3.45')
Decimal('4.68')

Câu hỏi: Trong ứng dụng điểm cố định có hai chữ số thập phân, một số đầu vào có nhiều vị trí và cần được làm tròn. Những số khác không được phép có chữ số dư thừa và cần được xác thực. Nên sử dụng những phương pháp nào?

Đáp: Phương thức quantize() làm tròn đến một số chữ số thập phân cố định. Nếu bẫy Inexact được đặt, nó cũng hữu ích cho việc xác thực:

>>> TWOPLACES = Decimal(10) ** -2       # same as Decimal('0.01')
>>> # Round to two places
>>> Decimal('3.214').quantize(TWOPLACES)
Decimal('3.21')
>>> # Validate that a number does not exceed two places
>>> Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Decimal('3.21')
>>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Traceback (most recent call last):
   ...
Inexact: None

Câu hỏi: Sau khi tôi có hai đầu vào vị trí hợp lệ, làm cách nào để duy trì tính bất biến đó trong suốt ứng dụng?

Đáp: Một số phép tính như cộng, trừ và nhân với một số nguyên sẽ tự động giữ nguyên điểm cố định. Các phép toán khác, như phép chia và phép nhân không nguyên, sẽ thay đổi số vị trí thập phân và cần được thực hiện tiếp bằng bước quantize():

>>> a = Decimal('102.72')           # Initial fixed-point values
>>> b = Decimal('3.17')
>>> a + b                           # Addition preserves fixed-point
Decimal('105.89')
>>> a - b
Decimal('99.55')
>>> a * 42                          # So does integer multiplication
Decimal('4314.24')
>>> (a * b).quantize(TWOPLACES)     # Must quantize non-integer multiplication
Decimal('325.62')
>>> (b / a).quantize(TWOPLACES)     # And quantize division
Decimal('0.03')

Khi phát triển các ứng dụng điểm cố định, sẽ thuận tiện hơn khi xác định các hàm để xử lý bước quantize():

>>> def mul(x, y, fp=TWOPLACES):
...     return (x * y).quantize(fp)
...
>>> def div(x, y, fp=TWOPLACES):
...     return (x / y).quantize(fp)
>>> mul(a, b)                       # Automatically preserve fixed-point
Decimal('325.62')
>>> div(b, a)
Decimal('0.03')

H: Có nhiều cách diễn đạt cùng một giá trị. Các số 200, 200.000, 2E2.02E+4 đều có cùng giá trị ở các độ chính xác khác nhau. Có cách nào để chuyển đổi chúng thành một giá trị chuẩn có thể nhận biết được không?

Trả lời: Phương pháp normalize() ánh xạ tất cả các giá trị tương đương vào một đại diện duy nhất:

>>> values = map(Decimal, '200 200.000 2E2 .02E+4'.split())
>>> [v.normalize() for v in values]
[Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2')]

Câu hỏi: Khi nào việc làm tròn xảy ra trong tính toán?

A: Nó xảy ra after tính toán. Triết lý của đặc tả thập phân là các con số được coi là chính xác và được tạo ra độc lập với bối cảnh hiện tại. Chúng thậm chí có thể có độ chính xác cao hơn bối cảnh hiện tại. Quá trình tính toán với các đầu vào chính xác đó và sau đó làm tròn (hoặc các thao tác ngữ cảnh khác) được áp dụng cho result của phép tính:

>>> getcontext().prec = 5
>>> pi = Decimal('3.1415926535') # More hơn 5 chữ số
>>> chữ số pi # All được giữ lại
Thập phân('3.1415926535')
>>> pi + 0 # Rounded sau khi cộng
Thập phân('3.1416')
>>> pi - Số thập phân('0.00005') # Subtract không làm tròn số, sau đó làm tròn
Thập phân('3.1415')
>>> pi + 0 - Số thập phân('0.00005').   giá trị # Intermediate được làm tròn
Thập phân('3.1416')

Hỏi: Một số giá trị thập phân luôn được in bằng ký hiệu số mũ. Có cách nào để có được một đại diện không theo cấp số nhân?

Trả lời: Đối với một số giá trị, ký hiệu hàm mũ là cách duy nhất để biểu thị số vị trí quan trọng trong hệ số. Ví dụ: biểu thị 5.0E+3 dưới dạng 5000 giữ giá trị không đổi nhưng không thể hiển thị ý nghĩa hai vị trí của bản gốc.

Nếu một ứng dụng không quan tâm đến việc theo dõi ý nghĩa, có thể dễ dàng loại bỏ số mũ và số 0 ở cuối, làm mất ý nghĩa nhưng vẫn giữ nguyên giá trị:

>>> def remove_exponent(d):
...     return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
>>> remove_exponent(Decimal('5E+3'))
Decimal('5000')

Câu hỏi: Có cách nào để chuyển đổi float thông thường thành Decimal không?

Trả lời: Có, bất kỳ số dấu phẩy động nhị phân nào cũng có thể được biểu thị chính xác dưới dạng Số thập phân mặc dù việc chuyển đổi chính xác có thể có độ chính xác cao hơn mức trực giác gợi ý:

>>> Số thập phân(math.pi)
Thập phân('3.141592653589793115997963468544185161590576171875')

Câu hỏi: Trong một phép tính phức tạp, làm cách nào để đảm bảo rằng tôi không nhận được kết quả giả do độ chính xác không đủ hoặc do làm tròn bất thường.

Đáp: Mô-đun thập phân giúp dễ dàng kiểm tra kết quả. Cách tốt nhất là chạy lại các phép tính với độ chính xác cao hơn và với nhiều chế độ làm tròn khác nhau. Các kết quả rất khác nhau cho thấy độ chính xác không đủ, các vấn đề về chế độ làm tròn, đầu vào không được điều chỉnh hoặc thuật toán không ổn định về mặt số.

Câu hỏi: Tôi nhận thấy rằng độ chính xác của ngữ cảnh được áp dụng cho kết quả của các thao tác chứ không phải cho đầu vào. Có điều gì cần chú ý khi trộn các giá trị có độ chính xác khác nhau không?

Đ: Vâng. Nguyên tắc là tất cả các giá trị được coi là chính xác và số học trên các giá trị đó cũng vậy. Chỉ có kết quả được làm tròn. Ưu điểm của đầu vào là "những gì bạn gõ là những gì bạn nhận được". Một điểm bất lợi là kết quả có thể trông kỳ lạ nếu bạn quên rằng dữ liệu đầu vào chưa được làm tròn:

>>> getcontext().prec = 3
>>> Số thập phân('3.104') + Số thập phân('2.104')
Thập phân('5.21')
>>> Số thập phân('3.104') + Số thập phân('0.000') + Số thập phân('2.104')
Thập phân('5.20')

Giải pháp là tăng độ chính xác hoặc buộc làm tròn đầu vào bằng phép toán cộng đơn:

>>> getcontext().prec = 3
>>> +Số thập phân('1.23456789') # unary cộng với việc kích hoạt làm tròn
Thập phân('1.23')

Ngoài ra, đầu vào có thể được làm tròn khi tạo bằng phương pháp Context.create_decimal():

>>> Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678')
Decimal('1.2345')

Câu hỏi: Việc triển khai CPython với số lượng lớn có nhanh không?

Đ: Vâng. Trong quá trình triển khai CPython và PyPy3, các phiên bản C/CFFI của mô-đun thập phân tích hợp thư viện libmpdec tốc độ cao để có được số học dấu phẩy động thập phân được làm tròn chính xác một cách chính xác tùy ý [1]. libmpdec sử dụng Karatsuba multiplication cho các số có kích thước trung bình và Number Theoretic Transform cho các số rất lớn.

Bối cảnh phải được điều chỉnh cho số học chính xác tùy ý. EminEmax phải luôn được đặt ở giá trị tối đa, clamp phải luôn là 0 (mặc định). Việc cài đặt prec cần được chú ý một chút.

Cách tiếp cận dễ dàng nhất để thử số học bignum là sử dụng giá trị tối đa cho prec [2]:

>>> setcontext(Ngữ cảnh(prec=MAX_PREC, Emax=MAX_EMAX, Emin=MIN_EMIN))
>>> x = Số thập phân(2) ** 256
>>>x/128
Thập phân('904625697166532776746648320380374280103671755200316906558262375061821325312')

Để có kết quả không chính xác, MAX_PREC quá lớn trên nền tảng 64-bit và bộ nhớ khả dụng sẽ không đủ:

>>> Thập phân(1) / 3
Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 1, trong <module>
Lỗi bộ nhớ

Trên các hệ thống có phân bổ quá mức (ví dụ: Linux), một cách tiếp cận phức tạp hơn là điều chỉnh prec theo số lượng RAM có sẵn. Giả sử bạn có 8GB RAM và dự kiến có 10 toán hạng đồng thời sử dụng tối đa 500MB mỗi toán hạng:

>>> nhập hệ thống
>>>
>>> # Maximum số chữ số cho một toán hạng sử dụng 500MB trong các từ 8 byte
>>> # with 19 chữ số mỗi từ (4 byte và 9 chữ số cho bản dựng 32 bit):
>>> maxdigits = 19 * ((500 * 1024**2) // 8)
>>>
>>> # Check cái này hoạt động được:
>>> c = Ngữ cảnh(prec=maxdigits, Emax=MAX_EMAX, Emin=MIN_EMIN)
>>> c.traps[Không chính xác] = Đúng
>>> setcontext(c)
>>>
>>> # Fill độ chính xác sẵn có với số chín:
>>> x = Thập phân(0).logic_invert() * 9
>>> sys.getsizeof(x)
524288112
>>> x + 2
Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 1, trong <module>
  thập phân.Không chính xác: [<class 'thập phân.Không chính xác'>]

Nói chung (và đặc biệt là trên các hệ thống không có phân bổ tổng thể), bạn nên ước tính các giới hạn chặt chẽ hơn nữa và đặt bẫy Inexact nếu tất cả các phép tính được mong đợi là chính xác.