Ý tưởng bài tập tính tiền điện

Các bác ơi có thể giải thích ý tưởng ở ví dụ bên dưới giúp em được không ạ, làm sao có thể tách 203 thành các phần bên dưới ạ. Em cảm ơn

Bạn biết được quy định về giá bán điện của Bộ Công Thương như sau:

Bậc Giá bán lẻ điện sinh hoạt bậc thang Giá (VND/kWh)
1 Cho kWh từ 0 đến 50 1,484
2 Cho kWh từ 51 đến 100 1,533
3 Cho kWh từ 101 đến 200 1,786
4 Cho kWh từ 201 đến 300 2,242
5 Cho kWh từ 301 đến 400 2,503
6 Cho kWh từ 401 trở lên 2,587

Với chỉ số điện tháng trước và tháng này ghi trên hóa đơn, bạn hãy tự tính lại số tiền điện phải trả để so sánh kết quả.

Lưu ý: tiền phải trả == tiền điện sử dụng + thuế VAT (10% tiền điện). Kết quả chỉ lấy phần nguyên.

Bạn vừa sống tháng đầu tiên ở căn nhà mới mua và sử dụng 203 kWh điện.

  • 50 kWh điện đầu tiên tốn 50 × 1484 = 7420050×1484=74200 (VND).
  • 50 kWh điện tiếp theo (từ 51 đến 100) tốn 50 × 1533 = 7665050×1533=76650 (VND).
  • 100 kWh điện tiếp theo (từ 101 đến 200) tốn 100 × 1786 = 178600100×1786=178600 (VND).
  • 3 kWh điện cuối cùng (từ 201 đến 203) tốn 3 × 2242 = 67263×2242=6726 (VND).

Vậy chi phí điện sinh hoạt của bạn là 74200 + 76650 + 178600 + 6726 = 33617674200+76650+178600+6726=336176 (VND). Và tổng số tiền bạn cần trả là 336176 + 336176 \times 10% = 369793.6336176+336176×10%=369793.6

  • Đây là code em đang hiểu:
public static void main(String[] args) {
	Scanner sc = new Scanner(System.in);
	int chiSoDien1 = sc.nextInt();
	int chiSoDien2 = sc.nextInt();
	int total = 0;
	int ans = chiSoDien2 - chiSoDien1;
	
	if(ans >= 0 && ans <= 50) {
		total = (int) (ans * 1484 + ans * 1484 * 0.1);
	}else if(ans >= 51 && ans <= 100) {
		
	}else if(ans >= 101 && ans <= 200) {
		
	}else if(ans >= 201 && ans <= 300) {
		
	}else if(ans >= 301 && ans <= 400) {
		
	}else {
		
	}
		 
	System.out.println(total);

Trừ đi và tính thôi. Thuế thì để tính vào cuối.

4 Likes

bác ơi, bác nêu rõ đc kg ạ, mình tạo 1 biến ans rồi thì giờ làm để mà từ 203kwh kia ra 50, 50, 100, 3 đc ạ


Bài này dễ mà , bạn nhìn vào biểu đồ này thì sẽ biết được ý tưởng

4 Likes

thế là cái biến ans mình tạo ra làm điều kiện đưa vào các khoảng, nhưng làm sao tự động nhập vào là sẽ biết đc để tách ra 50, 50, 100, 3 ấy ạ

so sánh thôi, với 1 tờ giấy và bút thì bạn định làm như thế nào để biết được cần tách ra thành các khoảng trên. Thử tự nghĩ thuật toán đã rồi hãy bắt đầu code

3 Likes

ví dụ bạn lấy 203/50 =4; dư 3;
như vậy ta chắc chắn tính được số tiền = dư * check(4+1)
còn lại dùng vòng thôi

public class Main {

    public static int check(int a) {
        if (a == 1) {
            return 1484;
        }
        if (a == 2) {
            return 1533;
        }
        if (a == 3 || a == 4) {
            return 1786;
        }
        if (a == 5 || a == 6) {
            return 2242;
        }
        if (a == 7 || a == 8) {
            return 2503;
        }

        return 2587;

    }

    public static void main(String[] args0) {
        int n = 203;
        int k = n / 50;
        int v = n % 50;
        int sotien = v * check(k + 1);
        for (int i = 1; i <= k; i++) {
            sotien = sotien + 50 * check(i);
        }
        System.out.println(sotien);

    }
}
3 Likes

cảm ơn bạn nhiều, mình đang làm theo if-else, kg dùng vòng lặp mà vẫn tính đc ấy :grin:

A post was merged into an existing topic: Duplicate posts will be moved here

có nhiều cách làm có thể cách mà , Mình cũng rảnh nên làm vui hihi

1 Like

oki oki :blush: :blush:

Hard code quá, bảng mức điện kia bạn nên bỏ vào mảng để code với nhiều giá điện khác nhau.

8 Likes

cách này tay to hard code quá, mai mốt giá và bậc điện thay đổi lại phải code lại từ đầu. Đơn giản nhất là cho vào mảng tách khoảng để tính từng khoảng giá điện tương tự cách mà 1 con người tính bằng giấy bút là ok rồi. Vừa nhanh vừa chính xác, mai mốt giá điện thay đổi chỉ cần sửa lại bảng giá là ok

6 Likes

Làm theo if-else đây các bác :grin:

import java.util.Scanner;

public class ElectricityBill {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int chiSoDien1 = sc.nextInt();
		int chiSoDien2 = sc.nextInt();
		int total = 0;
		int ans = chiSoDien2 - chiSoDien1;

		if (ans >= 0 && ans <= 50) {
			total = (int) (ans * 1484 + (ans * 1484 * 0.1));
		} else if (ans >= 51 && ans <= 100) {
			total = (int) (50 * 1484 + (ans - 50) * 1533 + ((50 * 1484 + (ans - 50) * 1533) * 0.1));
		} else if (ans >= 101 && ans <= 200) {
			total = (int) (50 * 1484 + 50 * 1533 + (ans - 100) * 1786
					+ ((50 * 1484 + 50 * 1533 + (ans - 100) * 1786) * 0.1));
		} else if (ans >= 201 && ans <= 300) {
			total = (int) (50 * 1484 + 50 * 1533 + 100 * 1786 + (ans - 200) * 2242
					+ ((50 * 1484 + 50 * 1533 + 100 * 1786 + (ans - 200) * 2242) * 0.1));

		} else if (ans >= 301 && ans <= 400) {
			total = (int) (50 * 1484 + 50 * 1533 + 100 * 1786 + 100 * 2242 + (ans - 300) * 2503
					+ ((50 * 1484 + 50 * 1533 + 100 * 1786 + 100 * 2242 + (ans - 300) * 2503) * 0.1));

		} else{
			total = (int) (50 * 1484 + 50 * 1533 + 100 * 1786 + 100 * 2242 + 100 * 2503 + (ans - 400) * 2587
					+ ((50 * 1484 + 50 * 1533 + 100 * 1786 + 100 * 2242 + 100 * 2503 + (ans - 400) * 2587) * 0.1));
		}
		System.out.println(total);
	}

}

:sweat_smile:

Tớ sẽ để lại đoạn code dưới đây cho cậu tham khảo cách tách bảng giá điện ra khỏi phần tính toán như thế nào.
Đoạn code này có 1 số đặc điểm:

  • Bảng giá điện được tách độc lập với công thức tính. Nó sẽ giúp cậu dễ dàng sửa giá điện, hay bổ sung bậc mới.
  • Sử dụng Stream API (Java 8+).
  • Đã được hạn chế dùng if - else nhất có thể.
  • Tiền được lưu dưới dạng BigInteger (do tiền Việt có tương đối nhiều số 0).
  • Kết quả của việc tính toán bill điện là string để giải quyết vấn đề tràn số.

Enum ElectricityPriceRule (chứa cái bảng quy định giá bán điện của bộ công thương - hay tri thức của bài toán):

import java.math.BigDecimal;

public enum ElectricityPriceRule {
  FIRST(1, 1, 50, 1_484),
  SECOND(2, 51, 100, 1_533),
  THIRD(3, 101, 200, 1_786),
  FOURTH(4, 201, 300, 2_242),
  FIFTH(5, 301, 400, 2_503),
  SIXTH(6, 401, Integer.MAX_VALUE, 2_587),
  ;
  
  int id;
  int kwhMin;
  int kwhMax;
  BigDecimal unitPrice;
  
  ElectricityPriceRule(int id, int kwhMin, int kwhMax, int unitPrice) {
    this.id = id;
    this.kwhMin = kwhMin;
    this.kwhMax = kwhMax;
    this.unitPrice = BigDecimal.valueOf(unitPrice);
  }
  
  BigDecimal priceOf(int consummedAmount) {
    if(consummedAmount < this.kwhMin) {
      return BigDecimal.ZERO;
    }
    
    return BigDecimal.valueOf(Math.min(consummedAmount, kwhMax) - kwhMin + 1).multiply(unitPrice);
  }
}

Class ElectricityBillCalculator: Tính toán giá điện.

import java.math.BigDecimal;
import java.util.stream.Stream;

public class ElectricityBillCalculator {
  private static final BigDecimal TAX_RATE = BigDecimal.valueOf(0.1); 

  public String calculate(int consummedAmount) {
    return Stream.of(ElectricityPriceRule.values())
      .map(rule -> rule.priceOf(consummedAmount))
      .reduce(BigDecimal.ZERO, BigDecimal::add)
      .multiply(BigDecimal.ONE.add(TAX_RATE))
      .toString();
  }
}

Test case:

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;

import org.junit.Test;

...
  @Test
  public void testCalculateElectricityBill() throws Exception {
    ElectricityBillCalculator calculator = new ElectricityBillCalculator();
    assertThat(calculator.calculate(203), is("369793.6"));
  }

Nếu không hiểu chỗ nào thì hỏi nhé cậu :smiley:

10 Likes

đây là code theo chuyên gia rồi à bạn :grin:, ngoại trừ chỗ stream(java 8 kia thì đọc cũng hiểu)

1 Like

cũng không hẳn là chuyên gia thì mới code kiểu thế đâu bạn, các bạn mới cũng nên định hướng code rành mạch như vậy từ sớm thì tốt hơn. Những bài dễ có thể đoán trước được dạng này bạn cố gắng viết ra giấy các bước tính toán mà 1 người dùng để tính là sẽ ra kết quả. Đừng bó hẹp mình vào 1 khuôn mẫu hay code của ai vì 1 bài toán có thể có nhiều cách tính

6 Likes

Có 1 lớp lưu thông tin giá:

class GiaDien{
    public int SoDien=1;
    public double DonGia = 0;
    public GiaDien(int sodien, double dongia){
        SoDien = sodien;
        DonGia = dongia;
        if(SoDien<0) SoDien = 0;
    }
}

Rồi sinh ra bảng giá:

List<GiaDien> BangGia = new List<GiaDien>(){
    new GiaDien(50,1484),
    new GiaDien(50,1533),
    new GiaDien(100,1786),
    new GiaDien(100,2242),
    new GiaDien(100,2503),
    new GiaDien(2000000000,2587)
};

Cuối cùng là tính một số bất kỳ:

double TinhTienDien(int tongsodien){
    if(tongsodien<=0) return 0;
    double sum =0;
    for(int idx = 0;idx<BangGia.Count; idx++){
        int sodien = tongsodien <= BangGia[idx].SoDien ? tongsodien : BangGia[idx].SoDien;
        sum += sodien * BangGia[idx].DonGia;
        tongsodien -= sodien;
        if(tongsodien<=0) break;
    }
    return sum;
}

Hoàn thành

7 Likes

Thật ra bài toán này mà làm theo OOP thì rất đơn giản.

  1. Mỗi đối tượng kWh có chi phí và index. Tháng này Hà Mã Tím đáng yêu dùng 300 kWh để tắm thì là 300 kWh objects.
  2. Mỗi object khi khởi tạo sẽ dùng index của mình, tự đối chiếu với bảng giá rồi set chi phí của mình.
  3. Chỉ cần lặp qua từng objects, tính tổng chi phí là xong.
6 Likes

Rất cảm ơn các bác ở trên, cách giải quyết bằng OOP giúp tui học hỏi được kha khá thứ hay ho.
Xin góp chút ý cho câu hỏi, nếu mà ko viết theo kiểu OOP. Thì bạn chỉ cần làm vậy:

public static long calcuteBill(int monthKwh){
        long bill= 0;
        final int[][] price = {{001, 1484},
                               {051, 1553},
                               {101, 1786},
                               {201, 2242},
                               {301, 2503},
                               {401, 2587}};
        for(int level = price.length - 1 ; level >= 0 ; level--){
            if( monthKwh >= price[level][0]) {
                bill += (monthKwh - price[level][0] + 1) * price[level][1];
                monthKwh = price[level][0] - 1;
            }
        }
        return bill;
    }
6 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?