【java】关于 float与double型数据输出后结果不一样的问题

Java字符串之StringToKenizer类分割字符串之计算手机话费总额

主要用到的是StringTokenizer类里的构造函数,用于切割字符串得到想要的子字符串。

import java.util.Scanner;
import java.util.Arrays;
import java.util.StringTokenizer;
public class StrTest {
    public static void main(String[] args) {
	     	// 请在Begin-End间编写代码
            /********** Begin **********/
            // 接收给定的话费清单(由三行组成)
           Scanner input=new Scanner(System.in);
           String str1=input.next();str1=str1+" ";
           String str2=input.next();str2=str2+" ";
           String str3=input.next();
            // 拼接三行字符串
            String str=str1.concat(str2.concat(str3));
            // 分隔字符串,累加每种物品的价格
           StringTokenizer str0=new StringTokenizer(str);
           float sum=0;
           while(str0.hasMoreTokens()){
                 String s1=str0.nextToken();
                 StringTokenizer s2=new StringTokenizer(s1,":");
                 String uless=s2.nextToken();
                 String uful=s2.nextToken();
                char a1[]=uful.toCharArray();//a1为所有数字,包括小数点,包括“元”
                char a2[]=Arrays.copyOfRange(a1,0,a1.length-1);//去“元”,后面这个索引是不包含
                String uful2=new String(a2);
                StringTokenizer s3=new StringTokenizer(uful2,".");
                char front[]=(s3.nextToken()).toCharArray();

                char rear[]=(s3.nextToken()).toCharArray();
                
                int item=0;
                for(int i=front.length-1;i>=0;i--){
                    sum+=(front[i]-'0')*(Math.pow(10,item));
                    item++;
                }
                item=1;
                for(int i=0;i<rear.length;i++){
                    sum+=(rear[i]-'0')*(Math.pow(0.1,item));
                    item++;
                    System.out.println(sum);
                }
           }
            // 输出话费总额
        System.out.print("话费总额为:"+sum);
        /********** End **********/
    }
}
测试输入:
套餐及固定费用:58.00元
移动增值业务费:3.00元
套餐外短信/彩信费:0.5元
—— 预期输出 ——
话费总额为:61.5

测试输入:
套餐及固定费用:68.00元
移动增值业务费:36.50元
套餐外短信/彩信费:0.5元
—— 预期输出 ——
话费总额为:105.0

测试输入:
套餐及固定费用:108.00元
移动增值业务费:20.04元
套餐外短信/彩信费:0.9元
—— 预期输出 ——
话费总额为:128.94

思路非常简单。

第一步:测试用例只能一个个接受,最后拼起来,为了方便切割,每个子字符串之间连接上一个“ ”。(突然发现好像没必要连起来)。

第二步:以“:”把字符串分割成两部分,弃去没有数字的那部分,由于分割的子字符串只能从前往后一个个接,故不得不用一个字符串uless接受这部分,并再用一个字符串uful接受有用的部分。

第三步:把uful转化成字符数组,用于剔去“元”这个于计算无用的字符。再把得到的字符数组转化成字符串,以“.”切割。

第四步:分别用front[]和rear[]来接受小数点前的整数部分后小数点后的小数部分,分别计算求和。

得到以下结果:

试输入:
套餐及固定费用:58.00元
移动增值业务费:3.00元
套餐外短信/彩信费:0.5元
—— 预期输出 —— 
话费总额为:61.5                            
—— 实际输出 ——
话费总额为:61.5

测试输入:
套餐及固定费用:68.00元
移动增值业务费:36.50元
套餐外短信/彩信费:0.5元
—— 预期输出 ——
话费总额为:105.0
—— 实际输出 ——
话费总额为:105.0

测试输入:
套餐及固定费用:108.00元
移动增值业务费:20.04元
套餐外短信/彩信费:0.9元
—— 预期输出 ——
话费总额为:128.94
—— 实际输出 ——
话费总额为:128.93999

最后一个结果不对。128.94与128.93999是怎么得到的呢?我的sum是由整数部分和小数部分依次求和得到的,难道是求和的过程除了问题?

依次打印求小数部分的sum值:

​
试输入:
套餐及固定费用:58.00元
移动增值业务费:3.00元
套餐外短信/彩信费:0.5元
—— 预期输出 —— 
话费总额为:61.5                            
—— 实际输出 ——
这一次的sum值为:58.0
这一次的sum值为:58.0
这一次的sum值为:61.0
这一次的sum值为:61.0
这一次的sum值为:61.5
话费总额为:61.5

测试输入:
套餐及固定费用:68.00元
移动增值业务费:36.50元
套餐外短信/彩信费:0.5元
—— 预期输出 ——
话费总额为:105.0
—— 实际输出 ——
这一次的sum值为:68.0
这一次的sum值为:68.0
这一次的sum值为:104.5
这一次的sum值为:104.5
这一次的sum值为:105.0
话费总额为:105.0

测试输入:
套餐及固定费用:108.00元
移动增值业务费:20.04元
套餐外短信/彩信费:0.9元
—— 预期输出 ——
话费总额为:128.94
—— 实际输出 ——
这一次的sum值为:108.0
这一次的sum值为:108.0
这一次的sum值为:128.0
这一次的sum值为:128.04
这一次的sum值为:128.93999
话费总额为:128.93999

​

其实很明显前两个测试用例没有出错就说明不太可能是算法的问题。想到之前的一道题:float与double型数据二进制算法不同,所以输入同样的值可能有不同的结果。

所以把sum更改为double型。

​
试输入:
套餐及固定费用:58.00元
移动增值业务费:3.00元
套餐外短信/彩信费:0.5元
—— 预期输出 —— 
话费总额为:61.5                            
—— 实际输出 ——
这一次的sum值为:58.0
这一次的sum值为:58.0
这一次的sum值为:61.0
这一次的sum值为:61.0
这一次的sum值为:61.5
话费总额为:61.5

测试输入:
套餐及固定费用:68.00元
移动增值业务费:36.50元
套餐外短信/彩信费:0.5元
—— 预期输出 ——
话费总额为:105.0
—— 实际输出 ——
话费总额为:105.0
这一次的sum值为:68.0
这一次的sum值为:68.0
这一次的sum值为:104.5
这一次的sum值为:104.5
这一次的sum值为:105.0

测试输入:
套餐及固定费用:108.00元
移动增值业务费:20.04元
套餐外短信/彩信费:0.9元
—— 预期输出 ——
话费总额为:128.94
—— 实际输出 ——
这一次的sum值为:108.0
这一次的sum值为:108.0
这一次的sum值为:128.0
这一次的sum值为:128.04
这一次的sum值为:128.94
话费总额为:128.94


​

这说明定义数值类型时尽量定义double类型,否则会有精度损失。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值