Giúp hộ về thuật giải! bài toán chia kẹo (1 người xem)

  • Thread starter Thread starter ThuNghi
  • Ngày gửi Ngày gửi
Liên hệ QC

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

Bác RollOver79 giúp hộ triển khai bài tóan trên.
Nếu tòan bộ SL chia là số âm thì nên sửa code thế nào.
Đính kèm file yêu cầu.
Nhờ Bác giúp hộ.

Xin cám ơn!

Bổ sung thêm, không phải lúc nào cũng số âm. Và thêm trường hợp số có 2 số lẻ, khi chia thường thêm các dòng =0 -> SlChia=0.
Nếu SL Chia là cả số âm và số dương thì hơi khó, còn của bác đảm bảo toàn bộ SL Chia là số âm thì em chỉ sửa lại code 1 chút xíu thôi. Ý tưởng là cứ coi toàn bộ nó là số dương(dùng hàm ABS để chuyển về số dương), chỉ khi nào đến kết quả chính thức thì mới cho nó là số âm là OK ngay. Bác xem lại code vẫn như vậy, chỉ sửa có mấy chỗ thôi.
 

File đính kèm

Nếu SL Chia là cả số âm và số dương thì hơi khó, còn của bác đảm bảo toàn bộ SL Chia là số âm thì em chỉ sửa lại code 1 chút xíu thôi. Ý tưởng là cứ coi toàn bộ nó là số dương(dùng hàm ABS để chuyển về số dương), chỉ khi nào đến kết quả chính thức thì mới cho nó là số âm là OK ngay. Bác xem lại code vẫn như vậy, chỉ sửa có mấy chỗ thôi.
Cám ơn bác. bác xem qua ví dụ sau thử và giúp mình
- Trường hợp SoCT A001 là tòan số âm thì thay
If curSLChoDu >= curSLNhanThieu Then
thành
I
f curSLChoDu <= curSLNhanThieu Then
- Nhưng nếu trở lại A002 thì tòan số dương thì dùng nguợc lại, có thể xin 1 cách tổng thể.
- Nếu số có 2 số lẻ, khai kiểu Double với số tiền lớn # 2 tỉ thì sẽ sinh ra những dòng có số 0.
Tôi đã thử dùng
If SLChia = 0 Then Exit Do 'thoat vong lap kho slchia =0
Cho SLChia, cách trên liệu có chính xác chưa!
Xin cám ơn.
 

File đính kèm

- Nhưng nếu trở lại A002 thì tòan số dương thì dùng nguợc lại, có thể xin 1 cách tổng thể.
- Nếu số có 2 số lẻ, khai kiểu Double với số tiền lớn # 2 tỉ thì sẽ sinh ra những dòng có số 0.
- Nghiệp vụ phức tạp quá, em đọc mãi mới hiểu. Về vấn đề lúc số âm, lúc số dương thì không đáng ngại. Phương án là ta quy hết về xử lý với số dương, khi trả ra giá trị mới xem nó là dương hay âm. Ở đây em dùng thêm 1 biến AmDuong có giá trị sẽ là 1 hoặc -1 tương ứng với 2 trường hợp âm hay dương, biến này được khởi gán 1 lần cho mỗi SoTK. Khi trả về giá trị thì nhân với biến AmDuong này là OK. Bác xem thử trong file.
- Còn vấn đề kiểu Double với giá trị lớn thì có lẽ là liên quan đến vấn đề sai số trong excel. Em chưa xem kỹ phần này, bác có dữ liệu thì post lên thử xem, vấn đề này nhiều người có thể giúp bác được.
 

File đính kèm

- Nghiệp vụ phức tạp quá, em đọc mãi mới hiểu. Về vấn đề lúc số âm, lúc số dương thì không đáng ngại. Phương án là ta quy hết về xử lý với số dương, khi trả ra giá trị mới xem nó là dương hay âm. Ở đây em dùng thêm 1 biến AmDuong có giá trị sẽ là 1 hoặc -1 tương ứng với 2 trường hợp âm hay dương, biến này được khởi gán 1 lần cho mỗi SoTK. Khi trả về giá trị thì nhân với biến AmDuong này là OK. Bác xem thử trong file.
- Còn vấn đề kiểu Double với giá trị lớn thì có lẽ là liên quan đến vấn đề sai số trong excel. Em chưa xem kỹ phần này, bác có dữ liệu thì post lên thử xem, vấn đề này nhiều người có thể giúp bác được.
Cám ơn bạn rất nhiều.

- Tôi thử vận dụng như sau về số âm
TH nếu tòan bộ là số âm thì dùng
TinhToan06
If curSLChoDu >= curSLNhanThieu Then
Còn không thì dùng TinhToan05
PHP:
If curSLChoDu <= curSLNhanThieu
Không biết logich trên liệu có OK.

- Bây giờ tôi đưa thêm 1 trường hợp số có 2 số lẻ.
Nếu tôi bỏ câu
If SLChia = 0 Then Exit Do 'thoat vong lap kho slchia =0
Thì do while không chịu dừng.
Nhờ bạn xem giúp. Dữ liệu trên đây chỉ dùng với Sub TinhToan05 và TinhToan06


Bổ sung thêm TH:
- Và thêm 1 trường hợp số có 2 số lẻ nữa.
Trường hợp có nhiều chứng từ mà có 2 số lẻ, khỏang 1.000 dòng
Nếu tôi không bỏ câu, vẫn giữ
If SLChia = 0 Then Exit Do 'thoat vong lap kho slchia =0
Thì trong lúc do while OK sẽ sinh ra những số gần = 0. Step thì thấy SlChia khi về 0 nó phải qua nhiều số 0.00000000....
 

File đính kèm

Lần chỉnh sửa cuối:
PHP:
Sub TinhToan05()
Dim curCho As Long, curNhan As Long
Dim curSLCho As Double, curSLNhan As Double
Dim curSLChoDu As Double, curSLNhanThieu As Double, SLChia As Double
curCho = 0: curNhan = 0
curSLNhanThieu = 0: curSLChoDu = 0: SLChia = 0
With Sheets("NKC")
  '***---------------------------------------------------------
  'Phan nay la nhieu no nhieu co
  Do While Not (curCho = rngCho.Rows.Count And curSLChoDu = 0)
    If curSLChoDu = 0 Then
      curCho = curCho + 1
      curSLCho = rngCho(curCho, 8)
      curSLChoDu = curSLCho
    End If
    If curSLNhanThieu = 0 Then
      curNhan = curNhan + 1
      curSLNhan = rngNhan(curNhan, 9)
      curSLNhanThieu = curSLNhan
    End If
    If curSLChoDu <= curSLNhanThieu Then
      SLChia = curSLChoDu
    Else
      SLChia = curSLNhanThieu
    End If
    If SLChia = 0 Then Exit Do 'thoat vong lap kho slchia =0
    .Cells(iRow, 1) = rngCho(curCho, 1)
    .Cells(iRow, 2) = sSoCT
    .Cells(iRow, 3) = rngCho(curCho, 3)
    .Cells(iRow, 4) = rngCho(curCho, 4)
    .Cells(iRow, ColTkNo) = rngCho(curCho, 7) ' TK No
    .Cells(iRow, ColTkCo) = rngNhan(curNhan, 7) 'TKCo
    .Cells(iRow, 7) = SLChia 'So tien
    curSLChoDu = curSLChoDu - SLChia
    curSLNhanThieu = curSLNhanThieu - SLChia
    .Cells(iRow, 12) = iCT Mod 2 'sott soct
    iRow = iRow + 1
  Loop

End With
End Sub
To: RollOver79
Mình có thay do while trên thành For i được không nhỉ?
Hay là khai biến kiểu khác double.
Mặc dù mình đã set =0
PHP:
curCho = 0: curNhan = 0
curSLNhanThieu = 0: curSLChoDu = 0: SLChia = 0
Mà sao SLChia=1.81898940354586E-12 <> 0
Làm sao khử nó nhỉ.
Bạn xem giúp mình nhé!
 
Các bạn giúp mình với.
Đã thử chuyển sang biến long và số tiền thì nhân 100, làm xong chia lại 100 thì chạy tốt. Không còn thấy SlChia gần = 0 như trên.
Nhưng hạn chế là số tiền PS chỉ được khỏan 20.000.000 v2 hạn chế biến long là 20 tr * 100.
Xin cám ơn!
 
Các bạn giúp mình với.
Đã thử chuyển sang biến long và số tiền thì nhân 100, làm xong chia lại 100 thì chạy tốt. Không còn thấy SlChia gần = 0 như trên.
Nhưng hạn chế là số tiền PS chỉ được khỏan 20.000.000 v2 hạn chế biến long là 20 tr * 100.
Xin cám ơn!
Xin lỗi bác, mấy hôm em bận ko vào xem được. Vấn đề của bác đúng là nan y thật. Không hiểu sao nó tự đẻ ra được 1 cái sai số trời ơi này. Tạm thời em thử thêm 1 cái điều kiện để kết thúc vòng lặp Do While như sau, bác xem có giải quyết được vấn đề không nhé:
Mã:
Do While Not ((curCho = rngCho.Rows.Count And curSLChoDu = 0) Or (curCho = rngCho.Rows.Count And curSLNhanThieu = 0))
Tuy nhiên đây cũng không phải là giải pháp triệt để, có lẽ phải nhờ các cao thủ khác nghiên cứu thêm cái vụ sai số này.
//Ồ hình như không đúng, em hiểu nhầm ý bác, đây chỉ là điều kiện để kết thúc vòng lặp, nếu nó vẫn còn dữ liệu để chia thì vẫn chết, chắc phải nghĩ thêm chút đã :(
 

File đính kèm

Lần chỉnh sửa cuối:
Xin lỗi bác, mấy hôm em bận ko vào xem được. Vấn đề của bác đúng là nan y thật. Không hiểu sao nó tự đẻ ra được 1 cái sai số trời ơi này. Tạm thời em thử thêm 1 cái điều kiện để kết thúc vòng lặp Do While như sau, bác xem có giải quyết được vấn đề không nhé:
Mã:
Do While Not ((curCho = rngCho.Rows.Count And curSLChoDu = 0) Or (curCho = rngCho.Rows.Count And curSLNhanThieu = 0))
Tuy nhiên đây cũng không phải là giải pháp triệt để, có lẽ phải nhờ các cao thủ khác nghiên cứu thêm cái vụ sai số này.
//Ồ hình như không đúng, em hiểu nhầm ý bác, đây chỉ là điều kiện để kết thúc vòng lặp, nếu nó vẫn còn dữ liệu để chia thì vẫn chết, chắc phải nghĩ thêm chút đã :(
Cám ơn bạn nhiều, tạm thời test thì đúng, nhưngđể mình gắn vào file chạy thử. Tức là không tìm ra lý do.
Cố gắng giúp mình nhé!
 
Cám ơn bạn nhiều, tạm thời test thì đúng, nhưngđể mình gắn vào file chạy thử. Tức là không tìm ra lý do.
Cố gắng giúp mình nhé!
Lý do chỗ này dài dòng lắm bác ạ, tạm thời để nó chạy chính xác bác tạm thời thay kiểu dữ liệu cho mấy biến này là Currency thay cho kiểu Double nhé. Chúc bác sớm hoàn thiện được chương trình của mình.
 
Lý do chỗ này dài dòng lắm bác ạ, tạm thời để nó chạy chính xác bác tạm thời thay kiểu dữ liệu cho mấy biến này là Currency thay cho kiểu Double nhé. Chúc bác sớm hoàn thiện được chương trình của mình.

PHP:
If SLChia = 0 Then Exit Do 'thoat vong lap khi slchia =0
Cám ơn bạn rất nhiều nhé, vấn đề câu trên có cần nữa không, thấy bỏ đi mà nó vẫn chạy.
 
PHP:
If SLChia = 0 Then Exit Do 'thoat vong lap khi slchia =0
Cám ơn bạn rất nhiều nhé, vấn đề câu trên có cần nữa không, thấy bỏ đi mà nó vẫn chạy.
Không cần dòng này nữa đâu, vòng lặp Do While đã bao hết các trường hợp để kết thúc rồi.
 
To: rollover79
Trở lại bài toán chia kẹo này, nhờ bạn chuyển các số thay vì gán xuống sheet qua những lần tinh toán 01, 02... thì mình gán vào array, sau khi xong mình gián xuống sh 1 lần luôn. Cụ thể như
PHP:
Sub TinhToan01()
'Truong hop nay danh cho 1N va 1C - Dem=2
With Sheets("NKC")
  .Cells(iRow, 1) = rngNhan(1, 1)
  .Cells(iRow, 2) = sSoCT
  .Cells(iRow, 3) = rngNhan(1, 3)
  .Cells(iRow, 4) = rngNhan(i, 4)
  .Cells(iRow, ColTkNo) = rngCho(1, 7) 'TKNo'
  .Cells(iRow, ColTkCo) = rngNhan(1, 7) 'TKCo;
  .Cells(iRow, 7) = rngNhan(1, 9) 'sotien
  .Cells(iRow, 12) = iCT Mod 2 'sott soct
   iRow = iRow + 1
End With
End Sub
Thay vì
.Cells(iRow, 1) = rngNhan(1, 1)
.Cells(iRow, 2) = sSoCT ...
Mình gán vào 1 Array
ArrKQ(iRow, 1)= rngNhan(1, 1)
ArrKQ(iRow, 2) = sSoCT ...
Và cứ khi các code tinhtoan run thì nó đưa kết quả appen vào ArrKQ. Khi nào iCT = eRow - 1 thì mới gán xuống Sheets("NKC")
Cám ơn nhiều.
Muốn dùng Arr cho nhanh hơn mà chưa biết cách gán theo từng code tinhtoan.
 

File đính kèm

Lần chỉnh sửa cuối:
To: rollover79
Trở lại bài toán chia kẹo này, nhờ bạn chuyển các số thay vì gán xuống sheet qua những lần tinh toán 01, 02... thì mình gán vào array, sau khi xong mình gián xuống sh 1 lần luôn. Cụ thể như
PHP:
Sub TinhToan01()
'Truong hop nay danh cho 1N va 1C - Dem=2
With Sheets("NKC")
  .Cells(iRow, 1) = rngNhan(1, 1)
  .Cells(iRow, 2) = sSoCT
  .Cells(iRow, 3) = rngNhan(1, 3)
  .Cells(iRow, 4) = rngNhan(i, 4)
  .Cells(iRow, ColTkNo) = rngCho(1, 7) 'TKNo'
  .Cells(iRow, ColTkCo) = rngNhan(1, 7) 'TKCo;
  .Cells(iRow, 7) = rngNhan(1, 9) 'sotien
  .Cells(iRow, 12) = iCT Mod 2 'sott soct
   iRow = iRow + 1
End With
End Sub
Thay vì
Mình gán vào 1 Array
Và cứ khi các code tinhtoan run thì nó đưa kết quả appen vào ArrKQ. Khi nào iCT = eRow - 1 thì mới gán xuống Sheets("NKC")
Cám ơn nhiều.
Muốn dùng Arr cho nhanh hơn mà chưa biết cách gán theo từng code tinhtoan.
Bài này lâu lắm mới lại mở lại, không nhớ được trước đây đã làm những gì :D. Tạm thời em thấy thế này, với trường hợp 01, chỉ có duy nhất 1 dòng nên không cần thiết phải dùng tới mảng làm gì. Trường hợp 02, 03, 04 thì đã thực hiện gán cả vùng nên nó cũng giống như mảng, thậm chí nếu dùng mảng còn mất công đọc vào mảng sẽ lâu hơn. Nên ở đây chỉ thấy có trường hợp 05 và 06 là có thể dùng thôi. Em sửa thử như trong file đính kèm bác kiểm tra thử xem sao nhé.
 

File đính kèm

Bài này lâu lắm mới lại mở lại, không nhớ được trước đây đã làm những gì :D. Tạm thời em thấy thế này, với trường hợp 01, chỉ có duy nhất 1 dòng nên không cần thiết phải dùng tới mảng làm gì. Trường hợp 02, 03, 04 thì đã thực hiện gán cả vùng nên nó cũng giống như mảng, thậm chí nếu dùng mảng còn mất công đọc vào mảng sẽ lâu hơn. Nên ở đây chỉ thấy có trường hợp 05 và 06 là có thể dùng thôi. Em sửa thử như trong file đính kèm bác kiểm tra thử xem sao nhé.
Cám ơn rất nhiều.
Cho mình hỏi
- Có thể khai array ở sub TaoRng(), cứ mỗi lần TinhToanX thì gắn vào Array thì có được không.
- Ở sub TaoRng() thay vì
Set rngCho = rngSoCTi.Offset(, -1).Resize(1, 8)
Set rngNhan = rngSoCTi.Offset(1, -1).Resize(1, 9)
Mình có thể chuyển thành Arr dạng như
Như vậy thì các sub TinhToan có ảnh hưởng gì nhiều? Và liệu có cải thiện thêm tốc độ.
Nếu bạn làm thì chỉ cần làm trên 1 sub tinhtoan4 và 1 thôi, mình sẽ triển khai tiếp.
Cám ơn RollOver nhiều.
 
Lần chỉnh sửa cuối:
Web KT

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

Back
Top Bottom