<span style="font-family: 微软雅黑, 宋体, Arial; background-color: rgb(255, 255, 255);">题目详情</span>
一份银行流水数据,因打印模糊导致部分金额不清楚。
收入、支出、余额满足以下3条规则:
1、收入、支出、余额三列都是数字
2、同一行收入和支出的值不能同时为非零值
3、第N-1行余额(+第N行收入或-第N行支出)=第N行余额
程序语言: java
请按照规则编写算法,修复不清楚的值
输入描述:
输入数据最多25行,每行都包含四个数据,分别是:数据编号,收入、支出、余额,模糊的数据以?表示,它们之间以;隔开。
以文件结尾。第一组数据为初始数据值,收入、支出、余额数据保留2位小数。
输出描述:
以输入的数据顺序输出修复后的数据。
输入样例:
流水记录ID;收入;支出;余额
1;0.00;51.90;1945.45
2;0.00;1000.00;?
输出样例:
流水记录ID;收入;支出;余额
1;0.00;51.90;1945.45
2;0.00;1000.00;945.45
############################################################################
代码修改多次,本地运行测试多组数据均没有问题,但在线测试始终出错,不知道是何原因?
**** 代码修改之后,考虑到了第一行模糊的情况,且测试多组数据如下,还是没有通过!!!:
初始账单如下:
流水记录ID;收入;支出;余额
1;10.00;?;1000.00;
2;10.02;?;?;
3;?;?;890.02;
4;?;?;?;
5;1000.00;0.00;?;
6;0.00;200.00;1900.00;
7;?;?;1780.00;
8;?;?;?;
9;?;10.00;2400.00;
10;100.00;?;?;
最终账单如下:
流水记录ID;收入;支出;余额
1;10.00;0.00;1000.00
2;10.02;0.00;1010.02
3;0.00;120.00;890.02
4;209.98;0.00;1100.00
5;1000.00;0.00;2100.00
6;0.00;200.00;1900.00
7;0.00;120.00;1780.00
8;630.00;0.00;2410.00
9;0.00;10.00;2400.00
10;100.00;0.00;2500.00
##代码采用递归思路实现,贴出代码如下##
##有更好的思路欢迎交流##
package com.study;
import java.io.*;
import java.math.*;
import java.util.Scanner;
/**
*
* @author
* @date 2014-08-06
*
* 一份银行流水数据,因打印模糊导致部分金额不清楚。
收入、支出、余额满足以下3条规则:
1、收入、支出、余额三列都是数字
2、同一行收入和支出的值不能同时为非零值
3、第N-1行余额(+第N行收入或-第N行支出)=第N行余额
程序语言: java
请按照规则编写算法,修复不清楚的值
输入描述:
输入数据最多25行,每行都包含四个数据,分别是:数据编号,收入、支出、余额,模糊的数据以?表示,它们之间以;隔开。
以文件结尾。第一组数据为初始数据值,收入、支出、余额数据保留2位小数。
输出描述:
以输入的数据顺序输出修复后的数据。
*
*/
@SuppressWarnings("unused")
public class WaterBill {
/**
* 记录账单:编号,收入,支出,余额
*/
static BigDecimal[][] bills=new BigDecimal[25][4];
static int length=0;//账单的实际编号
/**
* 一份神奇的银行流水,计算模糊流水账单
* @throws Exception
*/
@SuppressWarnings("resource")
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//BufferedReader bf=new BufferedReader(new FileReader("E:/java/bills.txt"));
int i=0;
//字符串形式读取账单详情
String[][] bill=new String[25][4];
String line = null;
System.out.println("请输入账单:(每输入一行以enter键开始下一行输入。以'EOF'结束)");
System.out.println("ID;"+"收入;"+"支出;"+"余额");
Scanner scn = new Scanner(System.in);
while (!"EOF".equals(line = scn.nextLine())) {
int j=0;
String[] vStrs = line.split(";");
for (String str : vStrs) {
bill[i][j++]=str;
}
i++;
length=i;
if(length>25){
System.out.println("提示:输入账单最多25行!");
System.exit(0);
}
}
/*
//字符串形式读取账单详情
BufferedReader bf=new BufferedReader(new FileReader("E:/java/bills.txt"));
String[][] bill=new String[25][4];
String line = null;
while ((line = bf.readLine()) != null) {
int j=0;
String[] vStrs = line.split(";");
for (String str : vStrs) {
bill[i][j++]=str;
}
i++;
length=i;
if(length>25){
System.out.println("提示:输入账单最多25行!");
System.exit(0);
}
}
*/
//将读取的数据转换成可用于计算的BigDecimal类型,并保留两位小数
//模糊数据用null表示
for(int k=0;k<length;k++){
for(int m=0;m<4;m++){
if(m==0){
bills[k][m]=new BigDecimal(bill[k][m]).setScale(0);
}else{
if(bill[k][m].equals("?")){
bills[k][m]=null;
}else{
bills[k][m]=new BigDecimal(bill[k][m]).setScale(2,BigDecimal.ROUND_HALF_UP);
}
}
}
}
System.out.println("初始账单如下:");
System.out.print("流水记录ID"+";"+"收入"+";"+"支出"+";"+"余额"+"\n");
for(int k=0;k<length;k++){
for(int m=0;m<4;m++){
if(bills[k][m]==null)
System.out.print("?"+";");
else
System.out.print(bills[k][m]+";");
}
System.out.println();
}
//计算模糊账单
new WaterBill();
System.out.println("\n最终账单如下:");
System.out.print("流水记录ID"+";"+"收入"+";"+"支出"+";"+"余额"+"\n");
for(int k=0;k<length;k++){
System.out.print(bills[k][0]+";"+bills[k][1]+";"+bills[k][2]+";"+bills[k][3]+"\n");
}
}
WaterBill(){
for(int i=0;i<length;i++){
for(int j=1;j<4;j++){
if(bills[i][j]==null){
bills[i][j]=countBills(i,j);
}
}
}
}
//计算模糊账单
BigDecimal countBills(int index,int indexY){
BigDecimal temp;
if(indexY==1){
//判断是否有多项均模糊
if(bills[index][2]==null){
//1、收入和支出均模糊
if(index==0){
System.out.println("初始账单的收入和支出均模糊,无法计算");
System.exit(0);
}
//如果余额也模糊,先计算出来
if(bills[index][3]==null){
bills[index][3]=countBills(index,3);
}
//计算(收入-支出)的值
temp=bills[index][3].subtract(bills[index-1][3]);
if(temp.compareTo(BigDecimal.ZERO)<0){
bills[index][1]=(BigDecimal.ZERO).setScale(2);
bills[index][2]=temp.abs();
}else{
bills[index][1]=temp;
bills[index][2]=(BigDecimal.ZERO).setScale(2);
}
}else{
//2、收入未知,支出非零,那么收入=0
if(bills[index][2].compareTo(BigDecimal.ZERO)!=0){
bills[index][1]=(BigDecimal.ZERO).setScale(2);
}else{
//3、收入未知,支出为零,计算结果
if(bills[index][3]==null)
bills[index][3]=countBills(index,3);
//递归回来之后bills[index-1][3]=null,无法计算
if(bills[index-1][3]==null){
System.out.println("模糊项太多,无法计算!!!");
System.exit(0);
}
bills[index][indexY]=bills[index][3].add(bills[index][2]).subtract(bills[index-1][3]);
}
}
}else if(indexY==2){
//判断是否有多项均模糊
if(bills[index][1].compareTo(BigDecimal.ZERO)!=0){
bills[index][2]=(BigDecimal.ZERO).setScale(2);
}else{
if(bills[index][3]==null)
bills[index][3]=countBills(index,3);
//递归回来之后bills[index-1][3]=null,无法计算
if(bills[index-1][3]==null){
System.out.println("模糊项太多,无法计算!!!");
System.exit(0);
}
bills[index][indexY]=bills[index-1][3].add(bills[index][1]).subtract(bills[index][3]);
}
}else if(indexY==3){
//余额计算可以与当月收支和上月余额相关,也可以与下月收支和下月余额相关
if(index==0){
for(int k=1;k<=3;k++){
if(bills[index+1][k]==null){
bills[index+1][k]=countBills(index+1, k);
}
}
}else{
if(bills[index][1]!=null&&bills[index][2]!=null&&bills[index-1][3]!=null){
bills[index][indexY]=bills[index-1][3].add(bills[index][1]).subtract(bills[index][2]);
}else{
if(index+1>length){
System.out.println("模糊项太多,无法计算!!!");
System.exit(0);
}
//判断第index+1行是否也有模糊项,若有,先计算出来
for(int k=1;k<=3;k++){
if(bills[index+1][k]==null){
bills[index+1][k]=countBills(index+1, k);
}
}
bills[index][indexY]=bills[index+1][3].add(bills[index+1][2]).subtract(bills[index+1][1]);
}
}
}
if(bills[index][indexY].compareTo(BigDecimal.ZERO)<0){
System.out.println("账单中不应该有负值");
System.exit(0);
}
//System.out.println((index+1)+","+indexY+":"+bills[index][indexY]);
return bills[index][indexY];
}
}