故事的开始
不知不觉在合租房中就混成了资历最老的住户,而算水费的工作也很自然的落在了我的头上。因为合租房中人员流动性很强,水费又攒了四个月没交,经过统计2017年12月到2018年3月这段时间共有11人需要交水费。于是算水费成了一件略头疼的事情。
算水费麻烦在于大家的时间都不一样。比如之前主卧到期了,主卧有一段时间空闲,然后住进来三个人中间又走了一个人。这只是主卧的情况,其他房间也都存在这种情况。
思路
这件事情首先需要想清楚思路。计算水费除非给每个人安一个水表是不能达到完全公平的,那么首先假定每人每天(人/天,这个单位很重要)用的水费都是一样的。平均算水费的关键在于这一段时间里一共有多少个人/天,用总钱数除掉所有的人/天,得到的就是每人/天的钱数,然后用每个人的天数乘以每人/天的钱数就是每个人要交的水费啦~
例子:有威尔逊和薇洛两个人合租。威尔逊住了一天,薇洛住了两天。水费一共9块,那么一共有3人/天,每人/天的水费是9/3=3,然后威尔逊的水费是31=3,薇洛的水费是32=6。
感觉完全是小学的数学题啊,其实就是计算略麻烦,用电脑算起来稍微简单点罢了。好了,思路捋清楚了就开始动手写代码了。
代码需要有两个输入,一是总钱数,二是每个人住的时间段。需要有一个输出是每个人要交的水费是多少。
代码
输入
最开始采用了控制台的输入方式。
private void inputFromConsole() {
Scanner scanner = new Scanner(System.in);
allMoney = Integer.parseInt(scanner.nextLine());
String nextLine = scanner.nextLine();
while(!nextLine.equals("0")) {
try {
String name = nextLine.split(" ")[0];
String time = nextLine.split(" ")[1];
String from = time.split(":")[0];
String end = time.split(":")[1];
int days = Utils.countInterval(from, end) + 1;
System.out.println("name:" + name + ",days:" + days);
waterBillList.add(new WaterBill(name, time, days, null));
nextLine = scanner.nextLine();
} catch (Exception e) {
//加一个容错,如果输入格式不对。可以重新输入。
nextLine = scanner.nextLine();
}
}
}
但是控制台输入方式太费劲,还容易出错。后来就改成了从excel中读取。
private void inputFromExcel(){
try {
FileInputStream inputStream = new FileInputStream(new File(excelFileName));
//读取工作簿
XSSFWorkbook workBook = new XSSFWorkbook(inputStream);
//读取工作表
XSSFSheet sheet = workBook.getSheetAt(0);
for (int i = 1; i < sheet.getLastRowNum(); i++) {
XSSFRow row = sheet.getRow(i);
XSSFCell cellName = row.getCell(0);
String name = cellName.getStringCellValue();
XSSFCell cellTime = row.getCell(1);
String time = cellTime.getStringCellValue();
String from = time.split(":")[0];
String end = time.split(":")[1];
int days = Utils.countInterval(from, end) + 1;
System.out.println("name:" + name + ",days:" + days);
XSSFCell cellDay = row.getCell(2);
cellDay.setCellValue(days);
waterBillList.add(new WaterBill(name, time, days, null));
}
allMoney = sheet.getRow(sheet.getLastRowNum()).getCell(1).getNumericCellValue();
workBook.write(new FileOutputStream(new File(excelFileName)));
inputStream.close();
workBook.close();//最后记得关闭工作簿
} catch (Exception e) {
e.printStackTrace();
}
}
计算
计算其实很简单,没几行代码。总之就是先算出每人/天的钱数,然后乘以每人的天数。
private void count() {
int allPersonOfDay = 0;
for (int i = 0; i < waterBillList.size(); i++) {
allPersonOfDay += waterBillList.get(i).getDays();
}
double averageMoney = allMoney / allPersonOfDay;
System.out.println("结果:");
for (int i = 0; i < waterBillList.size(); i++) {
String name = waterBillList.get(i).getName();
String bill = String.format("%.2f", averageMoney * waterBillList.get(i).getDays());
waterBillList.get(i).setBill(bill);
System.out.println("名字:" + name + ",账单:" + bill);
}
// createAndOutPutExcel(waterBillList);
outPutExcel(waterBillList);
}
输出
最后把结果输出的excel表格里,便于查看。
private void outPutExcel(List<WaterBill> waterBills) {
try {
FileInputStream inputStream = new FileInputStream(new File(excelFileName));
//读取工作簿
XSSFWorkbook workBook = new XSSFWorkbook(inputStream);
//读取工作表
XSSFSheet sheet = workBook.getSheetAt(0);
for (int i = 0; i < waterBills.size(); i++) {
XSSFRow row = sheet.getRow(i + 1);
XSSFCell cellName = row.getCell(3);
cellName.setCellValue(waterBills.get(i).getBill());
}
workBook.write(new FileOutputStream(new File(excelFileName)));
inputStream.close();
workBook.close();
} catch (Exception e) {
e.printStackTrace();
}
}
示例
计算需要按照水费单的两个月为一个周期,下面就只使用12月和1月的水单为示例。
首先整理一个表格把人名和对应的天数放进去。
点击运行就出来结果了。
最后
排版可以说惨不忍睹了。这件事也算是有点意思吧,解决现实生活中的问题了。
代码可以在这里下载 http://p06iwel4h.bkt.clouddn.com/waterBill.zip
欢迎关注【Funny新青年】微信公众号~