một cách hiệu quả để tìm số thập phân lặp lại là gì


24

Tôi đang cố gắng tìm một thuật toán hiệu quả trong Java để tìm phần thập phân lặp lại của hai số nguyên abở đâu a/b.

ví dụ. 5/7 = 0,714258 714258 ....

Tôi hiện chỉ biết phương pháp phân chia dài.


2
Vì vậy, bạn có a = 5 và b = 7, và bạn có thể tính a / b trong dấu phẩy động đủ dễ dàng, nhưng điều bạn muốn biết là nó có lặp lại sau 6 chữ số thập phân không?
Sparr

Câu trả lời:


10

Tôi tin rằng có hai cách tiếp cận chung ở đây, về cơ bản bạn có thể "vũ phu" tìm chuỗi lặp lại dài nhất hoặc bạn có thể giải quyết nó như một vấn đề của lý thuyết số.

Đã lâu rồi tôi mới gặp vấn đề này, nhưng trường hợp đặc biệt (1 / n) là vấn đề # 26 trên Project Euler, vì vậy bạn có thể tìm thêm thông tin bằng cách tìm kiếm các giải pháp hiệu quả cho tên cụ thể đó. Một tìm kiếm dẫn chúng tôi đến trang web của Eli Bendersky, nơi anh ấy giải thích giải pháp của mình . Đây là một số lý thuyết từ trang Mở rộng thập phân của Mathworld :

Bất kỳ phân số không m/nđều là định kỳ và có một khoảng thời gian lambda(n)độc lập m, n-1 dài tối đa các chữ số. Nếu nlà nguyên tố cùng nhau đến 10, sau đó giai đoạn lambda(n)của m/nlà một ước của phi(n)và có ít nhất phi(n)chữ số, trong đó philà hàm hàm Ơ-le. Hóa ra đó lambda(n)thứ tự nhân của 10 (mod n) (Glaisher 1878, Lehmer 1941). Số chữ số trong phần lặp lại của khai triển thập phân của số hữu tỷ cũng có thể được tìm thấy trực tiếp từ thứ tự nhân của mẫu số của nó.

Lý thuyết số của tôi là một chút gỉ tại thời điểm này, vì vậy điều tốt nhất tôi có thể làm là hướng bạn theo hướng đó.


8

Hãy n < dvà bạn đang cố gắng tìm ra phần lặp lại của n/d. Gọi plà số chữ số trong phần lặp lại: sau đó n/d = R * 10^(-p) + R * 10^(-2p) + ... = R * ((10^-p)^1 + (10^-p)^2 + ...). Phần ngoặc là một loạt hình học, bằng 1/(10^p - 1).

Vì vậy n / d = R / (10^p - 1). Sắp xếp lại để có được R = n * (10^p - 1) / d. Để tìm R, lặp ptừ 1 đến vô cùng và dừng lại ngay khi dchia đều n * (10^p - 1).

Đây là một triển khai trong Python:

def f(n, d):
    x = n * 9
    z = x
    k = 1
    while z % d:
        z = z * 10 + x
        k += 1
    return k, z / d

( ktheo dõi độ dài của chuỗi lặp lại, vì vậy bạn có thể phân biệt giữa 1/9 và 1/99 chẳng hạn)

Lưu ý rằng việc thực hiện này (trớ trêu thay) lặp đi lặp lại nếu việc mở rộng thập phân là hữu hạn, nhưng chấm dứt nếu nó là vô hạn! Tuy nhiên, bạn có thể kiểm tra trường hợp này bởi vì n/dsẽ chỉ có biểu diễn thập phân hữu hạn nếu tất cả các thừa số nguyên tố dkhông phải là 2 hoặc 5 cũng xuất hiện n.


1
Câu trả lời này có vẻ đúng. Phương pháp này dựa trên "quy tắc" sau: 0.123123... = 123/999 0.714258714258... = 714258/999999 (=5/7)v.v.
ĐẾN TỪ

4
Nó không thành công trong các trường hợp như 1/6 hoặc 5/12: \
razpeitia

1
@razpeitia Tôi đã làm một cái gì đó tương tự, nhưng hoạt động trong mọi trường hợp (bao gồm cả phân chia số nguyên). Kiểm tra: codepad.org/hKboFPd2
Tigran Saluev

Tôi đã thực hiện một triển khai javascript tương tự như @ TigranSaluev tại github.com/Macil/
Motorcycle

2

Phân chia dài? : /

Biến kết quả thành một chuỗi, và sau đó áp dụng thuật toán này cho nó. Sử dụng BigDecimal nếu chuỗi của bạn không đủ dài với các loại thông thường.


4
"Biến nó thành một chuỗi" có thể yêu cầu các phép tính chính xác tùy ý và một chuỗi rất dài để tính hai bản sao của phần lặp lại của chuỗi (và làm thế nào để bạn biết khi nào ngừng tính toán? .121212312121231212123 ... sẽ là một vấn đề)
Sparr

@Sparr Độ dài của sự lặp lại luôn nhỏ hơn mẫu số.

@MichaelT Tôi không biết điều đó. Nếu đúng, độ chính xác không chính xác là "tùy ý", nhưng có thể cao tùy ý tùy thuộc vào mẫu số.
Sparr

@Sparr math.stackexchange.com/questions/298844/ Mặc dù tôi tìm thấy mọi thứ2.com/title/recurring+ decimal dễ đọc hơn.

Tôi không nghĩ rằng thuật toán bạn liên kết sẽ hoạt động mà không sửa đổi. Nó bao gồm các lần lặp lại trùng lặp và nó tìm kiếm trên tất cả các chuỗi (không chỉ cho các trận đấu liên tiếp). Ví dụ, chuỗi con lặp lại dài nhất trong "chuối" là "ana".
Web_Designer
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.