CÔNG CỤ
MODULES
THAM KHẢO
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.

Tìm hiểu Mô-đun decimal của Python

Trong lập trình Python, việc tính toán với số thực nhị phân (float) đôi khi không đảm bảo được độ chính xác tuyệt đối do các giới hạn trong việc biểu diễn số. Để khắc phục vấn đề này, Python cung cấp mô-đun decimal giúp thực hiện các phép toán với số thập phân một cách chính xác và nhanh chóng. Trong bài viết, bạn sẽ tìm hiểu cách sử dụng mô-đun decimal để xử lý các phép toán số thập phân chính xác, cũng như cách điều chỉnh độ chính xác và cơ chế làm tròn của các phép toán này.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Giới thiệu về mô-đun decimal của Python

Nhiều số thập phân không có biểu diễn chính xác trong hệ thống số thực nhị phân, ví dụ như 0.1. Khi sử dụng các số này trong các phép toán, bạn có thể nhận được kết quả không như mong đợi. Ví dụ:

x = 0.1
y = 0.1
z = 0.1

s = x + y + z

print(s)

Kết quả là:

0.30000000000000004

Kết quả không phải là 0.3 như mong đợi.

Bài viết này được đăng tại [free tuts .net]

Để giải quyết vấn đề này, bạn có thể sử dụng lớp Decimal từ mô-đun decimal như sau:

import decimal
from decimal import Decimal

x = Decimal('0.1')
y = Decimal('0.1')
z = Decimal('0.1')

s = x + y + z

print(s)

Kết quả là:

0.3

Đầu ra như mong đợi.

Mô-đun decimal của Python hỗ trợ các phép tính toán chính xác tương tự như các phép toán bạn học ở trường.

Không giống như các số thực float, Python đại diện cho các số thập phân một cách chính xác. Và tính chính xác này được giữ nguyên trong các phép toán. Ví dụ, biểu thức sau trả về chính xác 0.0:

Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')

Ngữ cảnh (Context) của Decimal trong Python

Decimal luôn liên kết với một ngữ cảnh kiểm soát các khía cạnh sau:

  • Độ chính xác trong một phép toán
  • Thuật toán làm tròn

Theo mặc định, ngữ cảnh là toàn cục. Ngữ cảnh toàn cục là ngữ cảnh mặc định. Bạn cũng có thể thiết lập một ngữ cảnh tạm thời có hiệu lực cục bộ mà không ảnh hưởng đến ngữ cảnh toàn cục.

Để lấy ngữ cảnh mặc định, bạn gọi hàm getcontext() từ mô-đun decimal:

decimal.getcontext()

Hàm getcontext() trả về ngữ cảnh mặc định, có thể là toàn cục hoặc cục bộ.

Để tạo một ngữ cảnh mới sao chép từ ngữ cảnh khác, bạn sử dụng hàm localcontext():

decimal.localcontext(ctx=None)

Hàm localcontext() trả về một ngữ cảnh mới sao chép từ ngữ cảnh ctx nếu được chỉ định.

Sau khi có đối tượng ngữ cảnh, bạn có thể truy cập độ chính xác và cách làm tròn qua thuộc tính prec và rounding tương ứng:

  • ctx.prec: lấy hoặc đặt độ chính xác. ctx.prec là một số nguyên, mặc định là 28.
  • ctx.rounding: lấy hoặc đặt cơ chế làm tròn. Cách làm tròn là một chuỗi, mặc định là 'ROUND_HALF_EVEN'. Lưu ý các số thực float cũng sử dụng cơ chế làm tròn này.

Python cung cấp các cơ chế làm tròn sau:

Làm tròn Mô tả
ROUND_UP làm tròn ra xa số không
ROUND_DOWN làm tròn về số không
ROUND_CEILING làm tròn lên (về phía dương vô cùng)
ROUND_FLOOR làm tròn xuống (về phía âm vô cùng)
ROUND_HALF_UP làm tròn đến gần nhất, nếu bằng nhau thì làm tròn ra xa số không
ROUND_HALF_DOWN làm tròn đến gần nhất, nếu bằng nhau thì làm tròn về số không
ROUND_HALF_EVEN làm tròn đến gần nhất, nếu bằng nhau thì làm tròn đến số chẵn

Ví dụ này minh họa cách lấy độ chính xác và cách làm tròn mặc định của ngữ cảnh:

import decimal

ctx = decimal.getcontext()

print(ctx.prec)
print(ctx.rounding)

Kết quả:

28
ROUND_HALF_EVEN

Ví dụ sau cho thấy cách cơ chế làm tròn 'ROUND_HALF_EVEN' có hiệu lực:

import decimal
from decimal import Decimal

x = Decimal('2.25')
y = Decimal('3.35')

print(round(x, 1))
print(round(y, 1))

Kết quả:

2.2
3.4

Nếu bạn thay đổi cách làm tròn thành 'ROUND_HALF_UP', bạn sẽ nhận được kết quả khác:

import decimal
from decimal import Decimal

ctx = decimal.getcontext()
ctx.rounding = decimal.ROUND_HALF_UP

x = Decimal('2.25')
y = Decimal('3.35')

print(round(x, 1))
print(round(y, 1))

Kết quả:

2.3
3.4

Ví dụ sau đây cho thấy cách sao chép ngữ cảnh mặc định và thay đổi cách làm tròn thành 'ROUND_HALF_UP':

import decimal
from decimal import Decimal

x = Decimal('2.25')
y = Decimal('3.35')

with decimal.localcontext() as ctx:
    print('Ngữ cảnh cục bộ:')
    ctx.rounding = decimal.ROUND_HALF_UP
    print(round(x, 1))
    print(round(y, 1))

print('Ngữ cảnh toàn cục:')
print(round(x, 1))
print(round(y, 1))

Kết quả:

Ngữ cảnh cục bộ:
2.3
3.4
Ngữ cảnh toàn cục:
2.2
3.4

Lưu ý rằng ngữ cảnh cục bộ không ảnh hưởng đến ngữ cảnh toàn cục. Sau khối with, Python sử dụng cơ chế làm tròn mặc định.

Hàm tạo (Constructor) Decimal trong Python

Hàm tạo Decimal cho phép bạn tạo một đối tượng Decimal mới dựa trên một giá trị:

Decimal(value='0', context=None)

Tham số value có thể là số nguyên, chuỗi, tuple, số thực float, hoặc đối tượng Decimal khác. Nếu bạn không cung cấp tham số value, nó mặc định là '0'.

Nếu giá trị là một tuple, nó phải có ba thành phần: một dấu hiệu (0 cho số dương hoặc 1 cho số âm), một tuple của các chữ số, và một số mũ:

(sign, (digit1, digit2, digit3,...), exponent)

Ví dụ:

3.14 = 314 x 10^-2

Tuple có ba phần tử như sau:

  • sign là 0
  • digits là (3,1,4)
  • exponent là -2

Do đó, bạn sẽ cần phải truyền tuple sau cho hàm tạo Decimal:

import decimal
from decimal import Decimal

x = Decimal((0, (3, 1, 4), -2))
print(x)

Kết quả:

3.14

Lưu ý rằng độ chính xác của ngữ cảnh chỉ ảnh hưởng đến phép toán, không ảnh hưởng đến hàm tạo Decimal. Ví dụ:

import decimal
from decimal import Decimal

decimal.getcontext().prec = 2

pi = Decimal('3.14159')
radius = 1

print(pi)

area = pi * radius * radius
print(area)

Khi bạn sử dụng một số thực float không có biểu diễn chính xác trong hệ nhị phân, hàm tạo Decimal không thể tạo ra một biểu diễn thập phân chính xác. Ví dụ:

import decimal
from decimal import Decimal

x = Decimal(0.1)
print(x)

Kết quả:

0.1000000000000000055511151231257827021181583404541015625

Trong thực tế, bạn sẽ sử dụng chuỗi hoặc tuple để tạo Decimal.

Các phép toán số học Decimal trong Python

Một số toán tử số học không hoạt động giống như số thực float hoặc số nguyên int, chẳng hạn như div (//) và mod (%).

Đối với các số thập phân, toán tử // thực hiện phép chia bị cắt ngắn:

x // y = trunc( x / y)

Lớp Decimal cung cấp một số phép toán học như sqrt và log. Tuy nhiên, nó không có tất cả các hàm được định nghĩa trong mô-đun math.

Khi bạn sử dụng các hàm từ mô-đun math cho các số thập phân, Python sẽ chuyển đổi các đối tượng Decimal thành số thực float trước khi thực hiện các phép toán. Điều này dẫn đến mất độ chính xác đã được tích hợp trong các đối tượng Decimal.

Kết bài

Việc sử dụng mô-đun decimal của Python là cần thiết khi bạn muốn đảm bảo tính toán số thực thập phân chính xác và nhanh chóng. Với lớp Decimal từ mô-đun này, bạn có thể tạo đối tượng Decimal từ nhiều loại giá trị khác nhau như chuỗi, số nguyên và tuple. Đặc biệt, các số thập phân Decimal cho phép bạn kiểm soát độ chính xác và cơ chế làm tròn thông qua ngữ cảnh của chúng. Mặc dù lớp Decimal không cung cấp đầy đủ các phương thức như trong mô-đun math, bạn nên ưu tiên sử dụng các phương thức số học của Decimal để tận dụng độ chính xác và tính toán hiệu quả mà nó mang lại.

Cùng chuyên mục:

Ngoại lệ Raise trong Python

Ngoại lệ Raise trong Python

Tìm hiểu về các ngoại lệ trong Python

Tìm hiểu về các ngoại lệ trong Python

Tìm hiểu về decorator dataclass trong Python

Tìm hiểu về decorator dataclass trong Python

Ví dụ sử dụng metaclass trong Python

Ví dụ sử dụng metaclass trong Python

Lớp Metaclass trong Python

Lớp Metaclass trong Python

Tìm hiểu về Class Type trong Python

Tìm hiểu về Class Type trong Python

Phương thức __new__ trong Python

Phương thức __new__ trong Python

Phân biệt Data Descriptor và Non-data Descriptor trong Python

Phân biệt Data Descriptor và Non-data Descriptor trong Python

Mô tả Descriptors trong Python

Mô tả Descriptors trong Python

Tìm hiểu về các lớp mixin trong Python

Tìm hiểu về các lớp mixin trong Python

Đa kế thừa trong Python

Đa kế thừa trong Python

Nguyên tắc đảo ngược sự phụ thuộc trong Python

Nguyên tắc đảo ngược sự phụ thuộc trong Python

Interface Segregation Principle - ISP trong Python.

Interface Segregation Principle - ISP trong Python.

Nguyên tắc thay thế Liskov - LSP trong Python

Nguyên tắc thay thế Liskov - LSP trong Python

Nguyên tắc Đóng-Mở trong Python

Nguyên tắc Đóng-Mở trong Python

Single Responsibility Principle trong Python

Single Responsibility Principle trong Python

Cách sử dụng hàm Auto() của Python

Cách sử dụng hàm Auto() của Python

Tùy chỉnh và mở rộng lớp Enum trong Python

Tùy chỉnh và mở rộng lớp Enum trong Python

Sử dụng Enum aliases và @enum.unique trong Python

Sử dụng Enum aliases và @enum.unique trong Python

Cách sử dụng Protocol trong Python

Cách sử dụng Protocol trong Python

Top