Chuyển số thập phân thành số hữu tỉ ?? (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

Lệnh Hồ Đại Hiệp

Độc cô Cửu kiếm
Tham gia
20/10/08
Bài viết
299
Được thích
524
Nhân có bài này Tìm mối quan hệ giữa 2 nhóm số cho trước

Bài toán là : Có một số thập phân cho trước, ta biết rằng nó có thể được biểu diễn chính xác dưới dạng phân số (Số hữu tỉ), và mẫu số của nó sẽ <=10.000.000 (VD vậy thôi)

Vậy có cách nào tìm được chính xác phân số đó ??

VD :26.813/268.250 = 0,099955265610438
 
Nhân có bài này Tìm mối quan hệ giữa 2 nhóm số cho trước

Bài toán là : Có một số thập phân cho trước, ta biết rằng nó có thể được biểu diễn chính xác dưới dạng phân số (Số hữu tỉ), và mẫu số của nó sẽ <=10.000.000 (VD vậy thôi)

Vậy có cách nào tìm được chính xác phân số đó ??

VD :26.813/268.250 = 0,099955265610438
Vậy mời các cao thủ thử với Function sau:
PHP:
Function PhanSo(So as Double) As String
Dim i as Double
For i = 1 to 10000000
If i*So = Round(i*So,0) then
PhanSo = i*So & "/" & i
Exit For
End IF
Next i
End Function
 
Upvote 0
Vậy mời các cao thủ thử với Function sau:
PHP:
Function PhanSo(So as Double) As String
Dim i as Double
For i = 1 to 10000000
If i*So = Round(i*So,0) then
PhanSo = i*So & "/" & i
Exit For
End IF
Next i
End Function

Ta thấy 9899989/8756985 được biểu diễn dưới dạng số của Excel là 1,13052483246231

Nếu như công thức của Ca_dafi tiên sinh thì
= PhanSo(9899989/8756985) = 9899989/8756985

Tuy nhiên PhanSo(1,13052483246231) = ""

vậy giải pháp nào cho trường hợp này và các trường hợp tương tự ?? Tức là ta chỉ biết số thập phân (do excel thể hiện) mà không biết tỷ số nguyên gốc của nó ??

Nếu dùng :
PHP:
Function PhanSo(So As Double) As String
    Application.Volatile (False)
    Dim i As Long
    For i = 1 To 10000000
        If Round(So * i, 7) = Round(So * i, 0) Then
            PhanSo = Format(Round(So * i, 0), "#,##0") & "/" & Format(i, "#,##0")
            Exit Function
        End If
    Next
End Function

Thì

PhanSo(1,13052483246231) = 9899989/8756985

Tuy nhiên UDF này không phải lúc nào cũng chính xác.
 
Upvote 0
Xin góp ý thêm phần cần trên cho hàm For. Vì nếu chỉ có 10000000 nhiêu đây thôi thì hơi bị bí quá.
PHP:
Function PhanSo(So As Double) As String
    Application.Volatile (False)
    Dim i As Long
    For i = 1 To 10 ^ Val(Len(So))
        If Round(So * i, 7) = Round(So * i, 0) Then
            PhanSo = Format(Round(So * i, 0), "#,##0") & "/" & Format(i, "#,##0")
            Exit Function
        End If
    Next
End Function
Thân.
 
Upvote 0
Xin góp ý thêm phần cần trên cho hàm For. Vì nếu chỉ có 10000000 nhiêu đây thôi thì hơi bị bí quá.
PHP:
Function PhanSo(So As Double) As String
    Application.Volatile (False)
    Dim i As Long
    For i = 1 To 10 ^ Val(Len(So))
        If Round(So * i, 7) = Round(So * i, 0) Then
            PhanSo = Format(Round(So * i, 0), "#,##0") & "/" & Format(i, "#,##0")
            Exit Function
        End If
    Next
End Function
Thân.

Áp dụng công thức của tiên sinh : Phân số =9899989/87569859 =0,113052471627252 (Xấp xỉ)
PhanSo(9899989/87569859) = PhanSo(0,113052471627252) = 867.047/7.669.421

Vẫn chưa đúng tiên sinh ạ.

Vấn đề là làm sao vừa đúng, vừa đảm bảo được tốc độ. Nếu không tìm được số đúng 100% thì tìm số đúng nhất.

--CV--
 
Upvote 0
Bài toán này có liên quan đến các vấn đề:
1- Phân số tối giản
2- Bài toán gần đúng (xấp xỉ), làm tròn
do đó, từ biểu thức: a/b = c ; khi phân tích ngược lại chưa chắc đã cho kết quả c = a/b - điều này có nguồn gốc từ các phép làm tròn.
 
Upvote 0
Vâng quynh đài nói vậy thì tại hạ cũng xin đáp trả chiêu này: Code trên của quynh đài nếu dùng số này (0.924596041212827=(14,479,873/15,660,756)) thì không có đáp số luôn chứ chưa nói gì đúng hay sai nữa là. Còn việc nhanh hay chậm, chính xác đến cở nào thì còn phụ thuộc vào cái Round kia nữa. Vậy xem như không tính đi nha. Chỉ xét xem code chạy được số cực đại hay cực tiểu bao nhiêu trước đã. Và code của em vẫn đang chạy rất tốt đấy chứ. Thân.
 
Lần chỉnh sửa cuối:
Upvote 0
Vâng quynh đài nói vậy thì tại hạ cũng xin đáp trả chiêu này:
Code trên của quynh đài nếu dùng số này (0.924596041212827=(14,479,873/15,660,756)) thì không có đáp số luôn chứ chưa nói gì đúng hay sai nữa là.
Còn việc nhanh hay chậm, chính xác đến cở nào thì còn phụ thuộc vào cái Round kia nữa. Vậy xem như không tính đi nha. Chỉ xét xem code chạy được số cực đại hay cực tiểu bao nhiêu trước đã. Và code của em vẫn đang chạy rất tốt đấy chứ.
Thân.

Tại hạ đâu có nói Code của tại hạ là đúng đâu.
Lệnh Hồ Đại Hiệp đã viết:
PhanSo(1,13052483246231) = 9899989/8756985

Tuy nhiên UDF này không phải lúc nào cũng chính xác.

Tại hạ nêu ra chỉ để nói rằng Code của Ca_dafi chưa phải là tối ưu (Vì với số do Excel cung cấp thì không ra kết quả), nhưng cách này thì nếu cho số đúng thì nó dò đúng.

vậy huynh đài thử lại UDFF của huynh đài với số 9899989/87569859 =0,113052471627252 xem thế nào
vì tại hạ thử thì nó cho bằng 867.047/7.669.421

-- Chúc vui--
 
Upvote 0
Thực ra bài toán này chỉ là một phần của bài toán :

Giải phương trình 3 ẩn, nếu nghiệm là phân số thì biểu hiện dưới dạng phân số.

Vì bài của bác BNTT ( Tìm mối quan hệ giữa 2 nhóm số cho trước) có mấy ẩn giải ra bằng các hàm định thức, tuy nhiên đó là số thập phân. Vậy làm cách nào để có thể lấy số chính xác của nghiệm.

Cảm ơn nhiều.

--CV--
 
Upvote 0
Cái này mình chưa chắc là sai đâu vì có thể có những đồng phân giống nhau mà. Giống như việc bạn nhập 2/4 nhưng kết quả lại ra 1/2 vậy. Đó gọi là phân số tối giản bạn à!
a|b|c| 0.113052472|7669421|867047|c=a*b 0.113052472|87569859|9899989|c=a*b 0.113052472|96040837|10857654|c=a*b
Đại khái là như vậy! Thân.
 
Lần chỉnh sửa cuối:
Upvote 0
Cái này mình chưa chắc là sai đâu vì có thể có những đồng phân giống nhau mà.
Giống như việc bạn nhập 2/4 nhưng kết quả lại ra 1/2 vậy. Đó gọi là phân số tối giản bạn à!
a|b|c|
0.113052472|7669421|867047|c=a*b
0.113052472|87569859|9899989|c=a*b
0.113052472|96040837|10857654|c=a*b
Đại khái là như vậy!
Thân.

Hai phân số : 9899989/87569859 867.047/7.669.421

hoàn toàn khác nhau , không thể tối giản được. Vì 9899989/867.047 = 11,4180534619231

Vì vậy tại hạ vẫn mong có một phương pháp khả dĩ tối ưu hơn.

PHP:
If Round(So * i, 7) = Round(So * i, 0) Then

Tham số làm tròn ở hàm Round thứ nhất rất quan trọng, càng lớn thì sự chính xác lại càng cao. Đây chính là một yếu tố để hàm của Ca_dafi trở thành chính xác nhất.

--CV--

 
Upvote 0
Nếu với số 0,113052471627252 mà muốn có kết quả 9899989/87569859 thì bạn dùng 1 trong hai code dưới.
PHP:
Function PhanSo(So As Double) As String
    Application.Volatile (False)
    Dim i As Long
    For i = 1 To 10 ^ Val(Len(So))
        If Round(So * i, 7) = Round(So * i, 0) Then
            lan = lan + 1
            If lan = 9 Then
            PhanSo = Format(Round(So * i, 0), "#,##0") & "/" & Format(i, "#,##0")
            Exit Function
            End If
        End If
    Next
End Function
PHP:
Function PhanSo(So As Double) As String
    Application.Volatile (False)
    Dim i As Long
    For i = 10 ^ Val(Len(So)) To 1 Step -1
        If Round(So * i, 7) = Round(So * i, 0) Then
            lan = lan + 1
            If lan = 2 Then
            PhanSo = Format(Round(So * i, 0), "#,##0") & "/" & Format(i, "#,##0")
            Exit Function
            End If
        End If
    Next
End Function
Không trúng thì không làm quen với bạn đâu! Thật đó.... Heeeee
Thân.
 
Upvote 0
Nếu với số 0,113052471627252 mà muốn có kết quả 9899989/87569859 thì bạn dùng 1 trong hai code dưới.
PHP:
Function PhanSo(So As Double) As String
    Application.Volatile (False)
    Dim i As Long
    For i = 1 To 10 ^ Val(Len(So))
        If Round(So * i, 7) = Round(So * i, 0) Then
            lan = lan + 1
            If lan = 9 Then
            PhanSo = Format(Round(So * i, 0), "#,##0") & "/" & Format(i, "#,##0")
            Exit Function
            End If
        End If
    Next
End Function
PHP:
Function PhanSo(So As Double) As String
    Application.Volatile (False)
    Dim i As Long
    For i = 10 ^ Val(Len(So)) To 1 Step -1
        If Round(So * i, 7) = Round(So * i, 0) Then
            lan = lan + 1
            If lan = 2 Then
            PhanSo = Format(Round(So * i, 0), "#,##0") & "/" & Format(i, "#,##0")
            Exit Function
            End If
        End If
    Next
End Function
Không trúng thì không làm quen với bạn đâu! Thật đó.... Heeeee
Thân.

Vẫn chưa được :
PHP:
Function PhanSo(So As Double) As String
    Application.Volatile (False)
    Dim i As Long
    For i = 1 To 10 ^ Val(Len(So))
        If Round(So * i, 7) = Round(So * i, 0) Then
            lan = lan + 1
            If lan = 9 Then
            PhanSo = Format(Round(So * i, 0), "#,##0") & "/" & Format(i, "#,##0")
            Exit Function
            End If
        End If
    Next
End Function

Với phân số : 1/123.000.000 = 0,000000008130081 thì UDF của tiên sinh = 0/5
Còn của Ca_dafi tiên sinh = 1/123.000.000

xem có cách nào tốt hơn không nhỉ ??
 
Upvote 0
Tại hạ có cảm giác rằng bài này nếu giải bằng nhị phân rất tốt, tuy nhiên lại chưa tìm được hướng ra chính xác.

Còn các cách trên vẫn là "vét cạn". Mong các cao thủ chỉ giáo.

--CV--
 
Upvote 0
Biểu diễn thành phân số

Nhờ Lệnh Hồ Đại Hiệp test giúp code sau:
Mã:
Function PhanSo(c As Double) As String
Const mLong = 2147483647 - 1
Const e = 0.0000000001
Dim a As Long, b As Long
Dim Found As Boolean
    b = 0
    Do While (b < mLong) And (Not Found)
       b = b + 1
       Found = Abs((b * c) - CLng(b * c)) <= e
    Loop
    PhanSo = CLng(b * c) & " / " & (b)
End Function

(tôi đã test với một vài trường hợp thì thấy khá đúng)
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Cải tiến để hàm nhanh hơn khi mẫu số quá lớn (đối số quá nhỏ)

Mã:
Function PhanSo(d As Double) As String
Const mLong = 2147483647 - 1
Const e = 0.0000000001
Dim a As Double, b As Long, c As Double
Dim Found As Boolean
    If d = 0 Then
        PhanSo = "0"
        Exit Function
    End If
    If d < 1 Then c = 1 / d Else c = d
    b = 0
    Do While (b < mLong) And (Not Found)
       b = b + 1
       a = b * c
       Found = Abs((a) - CLng(a)) <= e
    Loop
    If d > 1 Then PhanSo = CLng(a) & " / " & (b) Else PhanSo = (b) & " / " & CLng(a)
End Function
 
Upvote 0
Cảm ơn bạn đã tham gia. Nhưng thật sự vấn đề này e rằng không có đáp án chính xác đâu. Nó chỉ có thể nằm trong 1 tầm định mức nào đó thôi. Riêng với code của bạn thì có 2 điểm cần lưu ý: +Nếu b > mLong thì code trên vô hiệu. +Nếu tỷ số lệch nằm ngoài e thì sao? Tức là nếu là số này thì sao: 1/12300000000 hoặc lớn hơn nữa vì đây mới 1E-11 à. Hàm Double lên đến 1E-308 lận. Và code này vẫn là code "vét cạn" và bị giới hạn chỉ số trên và chỉ số dưới. Vậy vấn đề này xin ngừng tại đây là được rồi. Càng tìm thì máy làm việc càng lâu và số càng lớn hơn thôi. Đi cùng với nó vẫn là giới hạn không thể vượt qua nổi đó chính là số do biến Double quy định 1E-308. Dù bạn có tính thế nào thì ngài Bill đã dự tính sẳn rồi, làm sao mà qua mặt được chứ.... Thân.
 
Lần chỉnh sửa cuối:
Upvote 0
Trước khi ngừng lại cho em góp vui thêm 1 code nữa đã nhé. Không biết có đúng không nhờ các bác test giúp.
Mã:
Function PhanSo(x As Double) As String
    Dim TuSo As Double, MauSo As Double
    Dim i As Double, Temp
    TuSo = 10 ^ (Len(x & "") - 1) * x
    MauSo = TuSo / x
    Dim bFound As Boolean
    Do While Not bFound And TuSo > 1
        bFound = True
        If WorksheetFunction.Floor(MauSo / TuSo, 1) = MauSo / TuSo Then
            MauSo = MauSo / TuSo
            TuSo = 1
            Exit Do
        Else
            Temp = WorksheetFunction.Ceiling(Sqr(TuSo), 1)
            For i = 2 To Temp
                If WorksheetFunction.Floor(TuSo / i, 1) = TuSo / i Then
                    If WorksheetFunction.Floor(MauSo / i, 1) = MauSo / i Then
                        TuSo = TuSo / i
                        MauSo = MauSo / i
                        bFound = False
                        Exit For
                    End If
                End If
            Next
        End If
    Loop
    PhanSo = TuSo & "/" & MauSo
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn bác. Bác đã xử lý được tình huống số 1 ở tử số rồi. Dòng "TuSo = 10 ^ (Len(x & "") - 1) * x" không ổn lắm. Và hiện thấy đáp số không chính xác, bác thử với số này xem 15235/1614512455 nó ra đáp số kỳ quá à. Thân.
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn bác. Bác đã xử lý được tình huống số 1 ở tử số rồi.
Dòng "TuSo = 10 ^ (Len(x & "") - 1) * x" không ổn lắm.
Và hiện thấy đáp số không chính xác, bác thử với số này xem 15235/1614512455 nó ra đáp số kỳ quá à.
Thân.
Xin lỗi các bác là dòng đó phải là thế này
Mã:
[COLOR=Black][B]TuSo = 10 ^ (Len(x & "") - InStr(1, x & "", ".")) * x[/B][/COLOR]
Em xin giải thích 1 chút về giải thuật trong đoạn code vừa rồi.
1. Đầu tiên đưa số thập phân x về dạng phân số chính xác bằng công thức
Mã:
    TuSo = 10 ^ (Len(x & "") - InStr(1, x & "", ".")) * x
    MauSo = TuSo / x
Ví dụ: 12.345 sẽ thành 12345/1000
Đây chính là phân số chính xác nhất của số thập phân.
2. Bước tiếp theo là tối giản phân số ban đầu bằng cách: Với 1 cặp tử số và mẫu số, ta cho i chạy từ 2 đến căn bậc 2 của Tử số, nếu cả tử và mẫu đều chia hết cho i thì thực hiện tính lại tử số và mẫu số bằng cách chia cả 2 cho i.
3. Lặp lại bước 2 cho tới khi từ 2 cho đến căn bậc 2 của tử số mà không tìm thấy số i thỏa mãn cả tử và mẫu đều chia hết thì dừng lại.
- Với thuật giải này thì dễ thấy là số vòng lặp sẽ giảm đi rất nhiều do số mà ta xét ở đây liên tục được chia cho 1 số.
(Đến đây em mới nhớ ra là mới xét trường hợp Mẫu chia hết cho Tử mà chưa xét đến Tử chỉ hết cho Mẫu, 1 chút nữa là việc duyệt không nhất thiết phải duyệt với Tử số mà ta sẽ duyệt số nhỏ hơn giữa tử số và mẫu số. Do trước em chỉ test trường hợp số thập phân < 0 nên quên mất ý này)
Xin được cập nhật lại code như sau:
Mã:
Function PhanSo(x As Double) As String
    Dim TuSo As Double, MauSo As Double
    Dim i As Double, Temp
    TuSo = 10 ^ (Len(x & "") - InStr(1, x & "", ".")) * x
    MauSo = TuSo / x
    Dim bFound As Boolean
    Do While Not bFound And TuSo > 1
        bFound = True
        If WorksheetFunction.Floor(MauSo / TuSo, 1) = MauSo / TuSo Then
            MauSo = MauSo / TuSo
            TuSo = 1
            Exit Do
        ElseIf WorksheetFunction.Floor(TuSo / MauSo, 1) = TuSo / MauSo Then
            TuSo = TuSo / MauSo
            MauSo = 1
            Exit Do
        Else
            Temp = WorksheetFunction.Ceiling(Sqr(TuSo), 1)
            If TuSo > MauSo Then Temp = WorksheetFunction.Ceiling(Sqr(MauSo),1)
            For i = 2 To Temp
                If WorksheetFunction.Floor(TuSo / i, 1) = TuSo / i Then
                    If WorksheetFunction.Floor(MauSo / i, 1) = MauSo / i Then
                        TuSo = TuSo / i
                        MauSo = MauSo / i
                        bFound = False
                        Exit For
                    End If
                End If
            Next
        End If
    Loop
    PhanSo = Format(TuSo, "#,##0") & "/" & Format(MauSo, "#,##0")
End Function
Chú ý: Các bác test thì nên test theo hướng xuất phát từ 1 số thập phân thay cho từ 1 phân số. Vì nếu test xuất phát từ 1 phân số thì trong quá trình chia để trả về kết quả có thể excel đã làm tròn mất rồi.
 
Lần chỉnh sửa cuối:
Upvote 0
Nhân có bài này Tìm mối quan hệ giữa 2 nhóm số cho trước

Bài toán là : Có một số thập phân cho trước, ta biết rằng nó có thể được biểu diễn chính xác dưới dạng phân số (Số hữu tỉ), và mẫu số của nó sẽ <=10.000.000 (VD vậy thôi)

Vậy có cách nào tìm được chính xác phân số đó ??

VD :26.813/268.250 = 0,099955265610438

Tóm tắt lại đề bài
c là số thập phân. Tìm 2 số nguyên ab sao cho a/b=c (b<=10.000.000)

Cách giải :

Để giải quyết triệt để bài này, tôi có hướng giải như sau:
Bước 1

Tìm 2 số aabb sao cho aa/bb=c
dễ dàng tìm được aa, bb. Ví dụ c=0,001234 thì aa=12345bb=1000000
Bước 2
+ So sánh bb với 10.000.000
- Nếu bb<=10.000.000: đáp số a=aab=bb
+ Nếu bb>10.000.000: tìm uớc số chung lớn nhất cc của aabb.
- Nếu có ƯSCLN: đáp số a=aa/ccb=bb/cc
- Nếu không có ƯSCLN: bài toán vô nghiệm

Còn vướn chỗ làm sao tìm được ƯSCLN. Tức là phải giải quyết được vấn đề số nguyên tố. Các bạn có cách nào tìm nhanh dược các số nguyên tố nhỏ hơn a và b?
 
Upvote 0
Tại sao lại có số nguyên tố trong đó vậy thầy? Em có hai cách tình nhanh số nguyên tố (A và B). Và (B nhanh hơn A) nhưng (B chiếm nhiều dung lượng lưu trữ hơn A). Vậy tạm thời em đem cách A lên trước nha:
PHP:
Public Function SoNguyenTo(so As Single) As Boolean     Application.Volatile (False)     Dim i As Single     If so  2 And Int(so) Mod 2 = 0) Then Exit Function       SoNguyenTo = True     If so = 2 Or so = 3 Or so = 5 Or so = 7 Then Exit Function     For i = 3 To Int(Sqr(so)) Step 2         If so Mod i = 0 Then SoNguyenTo = False: Exit Function     Next End Function
Thầy dùng Function này để xác định SNT. Thân.
 
Lần chỉnh sửa cuối:
Upvote 0

Cách giải :

Để giải quyết triệt để bài này, tôi có hướng giải như sau:
Bước 1

Tìm 2 số aabb sao cho aa/bb=c
dễ dàng tìm được aa, bb. Ví dụ c=0,001234 thì aa=12345bb=1000000
Bước 2
+ So sánh bb với 10.000.000
- Nếu bb<=10.000.000: đáp số a=aab=bb
+ Nếu bb>10.000.000: tìm uớc số chung lớn nhất cc của aabb.
- Nếu có ƯSCLN: đáp số a=aa/ccb=bb/cc
- Nếu không có ƯSCLN: bài toán vô nghiệm

Còn vướn chỗ làm sao tìm được ƯSCLN. Tức là phải giải quyết được vấn đề số nguyên tố. Các bạn có cách nào tìm nhanh dược các số nguyên tố nhỏ hơn a và b?
Giải thuật chính xác là như này đây, nhưng theo em thì nếu bb<10.000.000 thì ta vẫn nên tối giản cho đẹp(đương nhiên là nếu tác giả không yêu cầu thì thôi cho nhanh :)). Còn vấn đề tối giản thì thay vì tìm ƯSCLN thì em lặp để chia dần. Đến đây mới lại chợt nhớ ra là mình for từ Số nhỏ - 1 về căn bậc 2 với step là -1 thì số sẽ giảm nhanh hơn. Nhưng thôi xin phép không post lại code nữa, bác nào thử thay lại rồi test xem tốc độ có cải thiện hơn không nhé.
 
Upvote 0
Tại sao lại có số nguyên tố trong đó vậy thầy?
Mình nhớ hồi học số học ở phổ thông, muốn tối giản phân số thì phân tích tử và mẫu số thành tích các số nguyên tố, rồi đơn giản các số nguyên tố giống nhau trên tử và mẫu số.
 
Upvote 0
Mà hổi đó chỉ phân tích thành các SNT nhỏ hơn 20 thôi. Giờ đây thì phải nhỏ SQRT(số) đó lận. Thật là làm khó người quá và quá trình quét sẽ lâu hơn nữa. Vì còn phải xem có phân tích thành cặp số mấy nữa. Lại phải quét! Thật là mệt.... Nếu có thì cho em xin thuật toán đi! thì tốt hơn thầy ơi! Thân.
 
Lần chỉnh sửa cuối:
Upvote 0
Đây là bài toán chính

Thực ra bài toán này chỉ là một phần của bài toán :

Giải phương trình 3 ẩn, nếu nghiệm là phân số thì biểu hiện dưới dạng phân số.

Vì bài của bác BNTT ( Tìm mối quan hệ giữa 2 nhóm số cho trước) có mấy ẩn giải ra bằng các hàm định thức, tuy nhiên đó là số thập phân. Vậy làm cách nào để có thể lấy số chính xác của nghiệm.

Cảm ơn nhiều.

Giải thuật chính xác là như này đây, nhưng theo em thì nếu bb<10.000.000 thì ta vẫn nên tối giản cho đẹp(đương nhiên là nếu tác giả không yêu cầu thì thôi cho nhanh :)). Còn vấn đề tối giản thì thay vì tìm ƯSCLN thì em lặp để chia dần. Đến đây mới lại chợt nhớ ra là mình for từ Số nhỏ - 1 về căn bậc 2 với step là -1 thì số sẽ giảm nhanh hơn. Nhưng thôi xin phép không post lại code nữa, bác nào thử thay lại rồi test xem tốc độ có cải thiện hơn không nhé.

Thực ra ta cũng nên cho giới hạn của mẫu số. Theo như của excel thể hiện thì ta nên cho là (9*10^15)

Cảm ơn mọi người

--CV--
 
Upvote 0
Còn vướn chỗ làm sao tìm được ƯSCLN. Tức là phải giải quyết được vấn đề số nguyên tố. Các bạn có cách nào tìm nhanh dược các số nguyên tố nhỏ hơn a và b?

Mà hổi đó chỉ phân tích thành các SNT nhỏ hơn 20 thôi. Giờ đây thì phải nhỏ SQRT(số) đó lận. Thật là làm khó người quá và quá trình quét sẽ lâu hơn nữa. Vì còn phải xem có phân tích thành cặp số mấy nữa. Lại phải quét!
Thật là mệt....
Nếu có thì cho em xin thuật toán đi! thì tốt hơn thầy ơi!
Thân.

Tìm ƯSCLN của 2 số: dùng hàm này
Thuật Toán Euclid tìm ƯSCLN(a,b) - Tìm Ước Chung Lớn Nhất giữa 2 số a và b:
Gọi số lớn là a, số nhỏ là b

Lấy a chia cho b (số lớn chia cho số nhỏ) được thương = q, số dư = r ( b > r ).
+ Nếu r = 0 => ƯSCLN(a,b) = b
+ Nếu r <> 0, thì lấy b chia cho r (số lớn chia cho số nhỏ)
Và cứ thế tiếp tục ...
PHP:
Function UCLN(a As Long, b As Long) As Long
Dim Sl As Long, Sn As Long, Tmp As Long
If a > b Then
    Sl = a: Sn = b
    Else
        Sl = b: Sn = a
End If
boyxin:
Tmp = Sl Mod Sn
If Tmp > 0 Then
    Sl = Sn: Sn = Tmp: GoTo boyxin
End If
UCLN = Sn
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Chú ý: Các bác test thì nên test theo hướng xuất phát từ 1 số thập phân thay cho từ 1 phân số. Vì nếu test xuất phát từ 1 phân số thì trong quá trình chia để trả về kết quả có thể excel đã làm tròn mất rồi.

Em làm như sau:
Bước 1: chuyển số thập phân về dạng phân số thập phân (VD: 0.123 = 123/1000 = Tuso/Mauso)
Bước 2: Tìm ƯSCLN(Tuso,Mauso)
Bước 3: Chia cả Tuso, Mauso cho ƯSCLN đã tìm được ở bước 2 => Ta được phân số tối giản


  1. Các bác Test giùm xem cách này thế nào?
  2. Các bác phát triển giúp để có thể test với số có nhiều chữ số hơn
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Test!

  1. các bác test giùm xem cách này thế nào?
  2. các bác phát triển giúp để có thể test với số có nhiều chữ số hơn
Kết quả test: 0.123456789 = 123456789 / 1000000000
Kết quả dùng hàm của HVL: 0.123456789 = 13566680 / 109890109
 
Upvote 0
Loai hoay cả ngày hôm nay theo hướng phân tích tử số và mẫu số ra thừa số nguyên tố rồi tối giản. Ví dụ:
tử số ts=a*b*c*d
mẫu số ms=a*c*e*f
(với a, b, c, d, e, f là các số nguyên tố)
ts / ms = a*b*c*d / a*c*e*f = b*d / e*f (đơn giản được ac)

Nhưng làm sao phân tích được số ts, ms ra thừa số nguyên tố ? Phải sử dụng vòng lặp duyệt. Tính bỏ cuộc vì cách giải cũng không khác anh em mấy.
Tình cờ phát hiện ra mình đâu cần tìm chi nhiều số nguyên tố, vì các số dạng 10, 100, 1000, ..., 10000000 chỉ là tích của 2 số nguyên tố 2 và 5. Như vậy chỉ cần đơn giản tử số và mẫu số cho 2 và 5 mà thôi, không cần duyệt các số khác.
Bài toán quy về như sau:
1. Chuyển số thập phân về dạng phân số có tử số ts và mẫu số ms=10^n. Ví dụ 0,0123 > 123/10000 (ts=123, ms=10000)
2. Dùng vòng lặp chia tsms cho 2, 5 (nếu cả 2 chia hết). Lặp cho đến khi nào 2, 5 không chia hết cho cả ts, ms thì kết thúc

Mã:
Function SoHuuTy(soThapPhan As Double) As String
Dim soTren As Long, soDuoi As Long, nCham As Long
Dim strNum As String
strNum = Trim(Str(soThapPhan))
nCham = InStr(1, strNum, ".")
If nCham = 0 Then
  SoHuuTy = strNum & "/1"
  Exit Function
ElseIf nCham = 1 Then
  soTren = Val(Mid(strNum, 2))
  soDuoi = 10 ^ (Len(strNum) - 1)
Else
  soTren = Replace(strNum, ".", "")
  soDuoi = 10 ^ (Len(strNum) - InStr(1, strNum, "."))
End If
SoHuuTy = soTren & " / " & soDuoi
If soTren > 1 Then
  Do
    If soTren >= 2 And soTren Mod 2 = 0 Then
      soTren = soTren / 2
      soDuoi = soDuoi / 2
    ElseIf soTren >= 5 And soTren Mod 5 = 0 Then
      soTren = soTren / 5
      soDuoi = soDuoi / 5
    Else
      Exit Do
    End If
  Loop
End If
SoHuuTy = soTren & "/" & soDuoi
End Function
 
Upvote 0
Kết quả test: 0.123456789 = 123456789 / 1000000000
Kết quả dùng hàm của HVL: 0.123456789 = 13566680 / 109890109

Trong thực tế, dễ thấy

attachment.php
 

File đính kèm

  • Problems.JPG
    Problems.JPG
    10.8 KB · Đọc: 83
Lần chỉnh sửa cuối:
Upvote 0
Loai hoay cả ngày hôm nay theo hướng phân tích tử số và mẫu số ra thừa số nguyên tố rồi tối giản. Ví dụ: tử số ts=a*b*c*d mẫu số ms=a*c*e*f (với a, b, c, d, e, f là các số nguyên tố) ts / ms = a*b*c*d / a*c*e*f = b*d / e*f (đơn giản được ac) Nhưng làm sao phân tích được số ts, ms ra thừa số nguyên tố ? Phải sử dụng vòng lặp duyệt. Tính bỏ cuộc vì cách giải cũng không khác anh em mấy. Tình cờ phát hiện ra mình đâu cần tìm chi nhiều số nguyên tố, vì các số dạng 10, 100, 1000, ..., 10000000 chỉ là tích của 2 số nguyên tố 2 và 5. Như vậy chỉ cần đơn giản tử số và mẫu số cho 2 và 5 mà thôi, không cần duyệt các số khác. Bài toán quy về như sau: 1. Chuyển số thập phân về dạng phân số có tử số ts và mẫu số ms=10^n. Ví dụ 0,0123 > 123/10000 (ts=123, ms=10000) 2. Dùng vòng lặp chia tsms cho 2, 5 (nếu cả 2 chia hết). Lặp cho đến khi nào 2, 5 không chia hết cho cả ts, ms thì kết thúc
Cảm ơn thầy nhiều nhưng theo em thầy nên nghĩ ngơi thì hơn. Cần gì bận tâm quá vậy. Mà nói thật cách của thầy có nhiều giới hạn và chỉ giải được cho số thập phân có 11 chữ số thôi. Nhiều hơn là #Value! rồi. Và chỉ chia cho 2 và cho 5 thôi vậy cũng không ổn lắm. Em cung cấp thêm 1000 SNT đầu tiên cho thầy làm ví dụ cho vui nha! Nếu rãnh thầy xét giùm em những số lớn hơn. Còn không thì những code ở bài trên cũng đủ rồi và tương đối không sai gì mấy. Ví dụ như code này:
PHP:
Function PhanSo(So As Double) As String     Application.Volatile (False)     Dim i As Double, Temp As String     For i = 1 To 10 ^ Val(Len(So))         If Round(So * i, 10) = Round(So * i, 0) Then             PhanSo = Format(Round(So * i, 0), "#,##0") & "/" & Format(i, "#,##0")             Exit Function         End If     Next End Function
Có thể tính được cho số =121/14641 và kết quả là 1/121. Hoặc =169/17303 và kết quả là 13/1331. Vậy cũng đúng chứ nhỉ? Mặc dù những số quá lớn thì nó quét lâu nhưng kết quả đúng cho các số nhỏ cũng đủ dùng chứ không đến nỗi đâu bác. Thân.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Trong thực tế, dễ thấy

attachment.php
Đây chẳng qua là boyxin bị bác Bill lừa thôi, thực tế thì khi tính bởi excel nó đã bị làm tròn nên bác nghĩ 13566680/109890109=0.123456789 thôi, bác thử dùng Calculator của window tính thử xem nó ra bao nhiêu. Em tính thì nó ra thế này này 0.12345678899999999089999992629.
- To Po_Pi: Dùng vòng lặp từ đầu đến cuối thì quá lâu, và khi bác dùng Round thì vẫn bị giới hạn bởi sai số người dùng. Với con số 0.123456789 của bác HVL đưa ra thì code của bác chạy lâu quá nên không rõ đưa ra kết quả thế nào.
 
Upvote 0
Chuyển số thập phân thành phân số tối giản

Theo em, chủ đề này đến đây có thể coi là tạm ổn

Bước 1: chuyển số thập phân về dạng phân số thập phân (VD: 0.123 = 123/1000 = Tuso/Mauso)
  1. Số thập phân = x
  2. Tử số = Replace(x, ".", "")
  3. Mẫu số = Tử số / x
Bước 2: Tìm ƯSCLN(Tử số,Mẫu số)
Thuật Toán Euclid tìm ƯSCLN(a,b) - Tìm Ước Chung Lớn Nhất giữa 2 số a và b:
Gọi số lớn là a, số nhỏ là b

Lấy a chia cho b (số lớn chia cho số nhỏ) được thương = q, số dư = r ( b > r ).
+ Nếu r = 0 => ƯSCLN(a,b) = b
+ Nếu r <> 0, thì lấy b chia cho r (số lớn chia cho số nhỏ)
Và cứ thế tiếp tục ...

Bước 3
: Chia cả Tử số, Mẫu số cho ƯSCLN đã tìm được ở bước 2 => Ta được phân số tối giản
-----------------------------------------------------------------------------------

Toàn bộ code chuyển từ số thập phân về dạng phân số (tối giản) như sau:

(NGẮN GỌN, ĐƠN GIẢN, TÍNH TOÁN ÍT, CHÍNH XÁC => TỐC ĐỘ CỰC NHANH)
Còn hạn chế: chuyển đổi được số thập phân có số chữ số <11 (kể cả trước và sau dấu thập phân)
PHP:
Function STP_PS(x As Double) As String
    Dim Tu As Long, Mau As Long
    Tu = Replace(x, ".", ""): Mau = Tu / x
    STP_PS = Tu / UCLN(Tu, Mau) & " / " & Mau / UCLN(Tu, Mau)
End Function
Function UCLN(a As Long, b As Long) As Long
Dim r As Long
If a > b Then
    r = a Mod b
    Else: r = b Mod a
End If
If r = 0 Then
    UCLN = Application.Min(a, b)
    Else: UCLN = UCLN(Application.Min(a, b), r)
End If
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Mình xin gửi thêm một cách :
PHP:
Function SoSangPhanso(So As Double) As String
Dim Tu As Double, Mau As Double, Tuso As Double, Mauso As Double
Dim Pos As Byte, Digit As Byte, Temp As Double
Pos = InStr(1, So, ".", 1) + InStr(1, So, ",", 1)
Digit = Len(Mid(So, Pos + 1, 15))
Mau = 10 ^ Digit: Mauso = Mau
Tu = So * Mauso: Tuso = Tu
Do
    If Tu < Mau Then
        Temp = Tu: Tu = Mau: Mau = Temp
    End If
    Tu = Tu Mod Mau
Loop While Tu * Mau <> 0
SoSangPhanso = Tuso / (Tu + Mau) & "/" & Mauso / (Tu + Mau)
End Function

Theo mình nghĩ, rất ít khi người ta chuyển từ số thập phân sang phân số một cách chính xác. Mà chỉ chuyển thành phân số tương đối với một giới hạn sai số cho phép nhất định.

Bản thân số thập phân trước khi chuyển, nó đã là một số chưa chính xác vì đã được làm tròn từ kết quả của một phép chia dư nào đó. Nếu như ta dùng số này để chuyển thành phân số chính xác thì phân số này cũng không chính xác.

Như vậy, việc chuyển từ số thập phân sang phân số cho kết quả tương đối với một sai số nào đó (do ta chọn) có lẽ sẽ thực tiễn hơn.

VD : 1/3=0.333333333333333

dùng phép chuyển đổi chính xác : 0.333333333=333333333/1000000000

(ta không thể có nhiều hơn nữa số 3 sau phẩy vì giới hạn của biến )

Ở đây số ta cần lại là 1/3 chứ không phải là 333333333/1000000000

Vậy, ta sẽ giải quyết bài toán này với điều kiện : Tìm số hữu tỷ từ một phân số cho trước với một sai số cho phép :
PHP:
Function SoSangPhanso(So As Double, Optional Saiso As Double = 0) As String
 
Upvote 0
Và đây là kết quả :
Kết quả trả về rất gần với kết quả mong muốn, tốc độ lại nhanh.
Nếu như muốn kết quả trả về chính xác thì tùy theo trường hợp mà ta chon sai số nhỏ một tí.
VD

Cfract(370.333333333333)=1111/3
Cfract(0.333333333333333,0.00001)=1/3
Cfract(3.14285714285714,0.00001)=22/7

PHP:
Function CFract(So As Double, Optional Saiso As Double = 0) As String
Dim Tuso As Double, Mauso As Double
Do
    Tuso = Tuso + 1
    Mauso = Round(Tuso / Left(So, 15), 0)
    If Mauso = 0 Then Mauso = 1
Loop While Mauso = 1 Or Abs(Left(Tuso / Mauso, 15) - Left(So, 15)) > Saiso
CFract = Tuso & "/" & Mauso
End Function
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Mấy bác còn nghiên cứu vấn đề này nữa à!
Em tìm mãi nhưng vẫn chưa có đáp số như ý muốn được.
Với code của bác hoangdanh282vn thì Tử số 11, mẫu số 121 thì nó toàn ra 100/11 không hà! Hiện chưa biết làm sao để ra được kết quả 1/11.
Bác thử test lại xem.
Thân.
 
Upvote 0
Mấy bác còn nghiên cứu vấn đề này nữa à!
Em tìm mãi nhưng vẫn chưa có đáp số như ý muốn được.
Với code của bác hoangdanh282vn thì Tử số 11, mẫu số 121 thì nó toàn ra 100/11 không hà! Hiện chưa biết làm sao để ra được kết quả 1/11.
Bác thử test lại xem.
Thân.

Cám ơn Po_Pikachu!

Minh đã test lại và nhận thấy rằng, do chức năng AutoFormat Number của excel nên dùng hàm Left sẽ bị sai, chỉnh lại một tí :

Với Hàm CFract ngắn gọn này, chuyển đổi số cực kỳ nhanh, chính xác và không bị giới hạn số lẻ (Với một sai số hợp lý)

Cfract(0.333333333333333,0.0000000001) = 1/3
Cfract(0.666666666666667,0.0000000001) = 2/3
Cfract(0.0909090909090909,0.0000000001) = 1/11
Cfract(1.01801801801802,0.0000000001) = 113/111
Cfract(1091.83826838268,0.0000000001) = 12131415/11111

PHP:
Function CFract(So As Double, Optional Saiso As Double = 0) As String
Dim Tuso As Double, Mauso As Double
Do
Tuso = Tuso + 1
Mauso = Round(Tuso / So, 0)
If Mauso = 0 Then Mauso = 1
Loop While Mauso = 1 Or Abs(Tuso / Mauso - So) > Saiso
CFract = Tuso & "/" & Mauso
End Function
 

File đính kèm

Upvote 0
Xin được sửa code của boyxin 1 chút để không bị giới hạn bởi 11 chữ số.
Mã:
Function STP_PS(x As Double) As String
    Dim Tu As Double, Mau As Double
    Tu = Replace(x, ".", ""): Mau = Tu / x
    STP_PS = Tu / UCLN(Tu, Mau) & " / " & Mau / UCLN(Tu, Mau)
End Function
Function UCLN(a As Double, b As Double) As Long
Dim r As Double
If a > b Then
    r = a - WorksheetFunction.Floor(a, b)
Else
    r = b - WorksheetFunction.Floor(b, a)
End If
If r = 0 Then
    UCLN = Application.Min(a, b)
    Else: UCLN = UCLN(Application.Min(a, b), r)
End If
End Function
Có lẽ đây là cách ổn nhất rồi, cách của hoangdanh vẫn duyệt toàn bộ, không đảm bảo về mặt tốc độ. Nếu với số 0.123456789 mà không có sai số thì treo ngay.
 
Upvote 0
@hoangdanh282vn: Code của bác chạy rất tốt. Mặt dù có lúc nó rút gọn chẳng đúng gì hết. Ví dụ như: =10/542694 KQ: 2/108539. Đúng ra nó nên chia 2 thì lại chia cho 5. Chẳng hiểu nữa.

@rollover79: Code của bác thì chỉ áp dụng cho các số thập phân thôi còn thập phân của một phép chia thì nó toàn báo lỗi #Value!.

Và đáp số cũng không chính xác gì hết. Ví dụ:
Số|hoangdanh282vn|rollover79
0.222273|7782/35011|222273 / 1000000
Thân.
 
Lần chỉnh sửa cuối:
Upvote 0
@hoangdanh282vn: Code của bác chạy rất tốt. Mặt dù có lúc nó rút gọn chẳng đúng gì hết. Ví dụ như: =10/542694 KQ: 2/108539. Đúng ra nó nên chia 2 thì lại chia cho 5. Chẳng hiểu nữa.

@rollover79: Code của bác thì chỉ áp dụng cho các số thập phân thôi còn thập phân của một phép chia thì nó toàn báo lỗi #Value!.

Và đáp số cũng không chính xác gì hết. Ví dụ:
Số|hoangdanh282vn|rollover79
0.222273|7782/35011|222273 / 1000000
Thân.
Hình như là bác đưa vào 1 phép chia ra số vô tỉ thì phải, ví dụ bác đưa vào 1/3 thì ra #VALUE là đúng rồi. Còn bác đưa vào phép chia hữu tỉ thì nó vẫn cho ra kết quả như thường. Còn cách của hoangdanh thì bác đọc lại thuật toán xem. hoangdanh xuất phát từ tử số là 1 và tính theo sai số chứ đâu có bước tối giản kết quả đâu. Nên nó ra kết quả như vậy là đúng rồi. Còn cái kết quả test như trên là chính xác đấy chứ sao lại ko chính xác nhỉ?
 
Upvote 0
@hoangdanh282vn: Code của bác chạy rất tốt. Mặt dù có lúc nó rút gọn chẳng đúng gì hết. Ví dụ như: =10/542694 KQ: 2/108539. Đúng ra nó nên chia 2 thì lại chia cho 5. Chẳng hiểu nữa.

@rollover79: Code của bác thì chỉ áp dụng cho các số thập phân thôi còn thập phân của một phép chia thì nó toàn báo lỗi #Value!.

Và đáp số cũng không chính xác gì hết. Ví dụ:
Số|hoangdanh282vn|rollover79
0.222273|7782/35011|222273 / 1000000
Thân.

Đơn giản thôi Po_pikachu à.
Giờ bạn thử cho sai số giảm đi 10 lần xem sao : saiso=0.00000000001

To @rollover79 : Thực ra code của bạn chỉ là việc thực hiện tính UCLN giữa 2 số mà thôi, chứ còn tìm ra số hữu tỉ thì quá đơn giản. VD 0.333333 thì biết ngay là 333333/10000000, không cần dùng Code gì cả.
Nhưng đó không phải là kết quả mong muốn như Po_Pikachu đã nói.
VD : với số 1,091.83826838, bạn thử cho ra kết quả 12131415/1111 xem mất bao lâu. Hiện giờ nó bị lỗi.
 
Upvote 0
VD : với số 1,091.83826838, bạn thử cho ra kết quả 12131415/1111 xem mất bao lâu. Hiện giờ nó bị lỗi.
Với số 1,091.83826838 thì code mà tôi sửa lại của boyxin ra 54591913419 / 50000000 với tốc độ cực nhanh. Còn của hoangdanh với sai số là 0.00000001 thì ra 12131415/11111, nhưng tốc độ thì tương đối chậm. Còn việc với số 0.333333 nó cho ra 333333/1000000 thì đây là kết quả chính xác. Vì số này không tối giản được nữa.
 
Upvote 0
Vâng, em biết đó là số đúng nhưng trong tính toán người ta không bao giờ cho bác sẵn 1 số thập phân rồi bắt bác tính phân số đâu. Ví dụ như người ta sẽ cho:
=(Sum(A1:D3)+Sum(E10:F11)/Sum(C1:E1)
Và bắt hiển thị ở dạng phân số thì sao?
Vậy chẳng phải vô ích sao?
Thì code của bác đúng nhưng áp dụng vào thực tế thì hơi thiếu sót đó!
Thân.
 
Upvote 0
Với số 1,091.83826838 thì code mà tôi sửa lại của boyxin ra 54591913419 / 50000000 với tốc độ cực nhanh. Còn của hoangdanh với sai số là 0.00000001 thì ra 12131415/11111, nhưng tốc độ thì tương đối chậm. Còn việc với số 0.333333 nó cho ra 333333/1000000 thì đây là kết quả chính xác. Vì số này không tối giản được nữa.

Mình đã test với số trên, với Ram1G, mất 5.03s, cũng chấp nhận được.
Vâng, em biết đó là số đúng nhưng trong tính toán người ta không bao giờ cho bác sẵn 1 số thập phân rồi bắt bác tính phân số đâu. Ví dụ như người ta sẽ cho:
=(Sum(A1:D3)+Sum(E10:F11)/Sum(C1:E1)
Và bắt hiển thị ở dạng phân số thì sao?
Vậy chẳng phải vô ích sao?
Thì code của bác đúng nhưng áp dụng vào thực tế thì hơi thiếu sót đó!
Thân.

Có chứ Po_Pikachu
VD trong giải hệ phương trình , nếu dùng mấy tính để giải thì kêt quá có thể sẽ là một số thập phân, cái mà ta cần là phân số. Hay bài toán chuyển đổi từ số sang radian hay góc sang Radian
từ số 1.83259571459405 tương đương với 7Pi/12, mà cái này trong toán hay vật lý thì rất cần
 
Lần chỉnh sửa cuối:
Upvote 0
Bài toán là : Có một số thập phân cho trước, ta biết rằng nó có thể được biểu diễn chính xác dưới dạng phân số (Số hữu tỉ), và mẫu số của nó sẽ <=10.000.000 (VD vậy thôi)
Vậy có cách nào tìm được chính xác phân số đó ??
Vậy thì phải xem lại yêu cầu của bài toán ban đầu là thế này. Còn khi bác muốn đưa 1 số vô tỉ(1 phân số) vào thì bác phải dùng thêm hàm làm tròn để đảm bảo nó là số hữu tỉ đã.
 
Upvote 0
Mình còn 1 cách dùng công thức thường minh họa theo code của anh Boyxin, dễ hiểu và tốc độ cũng nhanh.

=FIXED(SUBSTITUTE(A1,".","")/GCD(SUBSTITUTE(A1,".",""),SUBSTITUTE(A1,".","")/A1),0)&"/"&FIXED(SUBSTITUTE(A1,".","")/GCD(SUBSTITUTE(A1,".",""),SUBSTITUTE(A1,".","")/A1)/A1,0)

Khi giải quyết một vấn đề gì, mình đều xem xét mọi khía cạnh của vấn đề đó. Vì thế, trong quá trình tranh luận, có gì không phải mong các bạn thông cảm bỏ qua cho.
 

File đính kèm

Upvote 0
Còn một cách khá "dã man" và không cần code kiết gì cả! Hãy format ô chứa số thập phân đó ở dạng Fraction (Format cell/Number -->Fraction--> Up to three digits 312/943). Và dĩ nhiên với cách này, số liệu đương nhiên là có thể dùng để tính toán được và ta có thể "nhìn thấy" phân số đó ở dạng hữu tỉ.
Thậm chí, ví dụ: 123/10 = 12 3/10

Tuy nhiên, hạn chế của nó chỉ giới hạn ở 3 digits, nếu gõ 7/8000 nó sẽ trả về 0
 
Lần chỉnh sửa cuối:
Upvote 0

Bài viết mới nhất

Back
Top Bottom