浮点数的注意事项

浮点数判断相等问题

啤酒和饮料

啤酒每罐2.3元,饮料每罐1.9元。小明买了若干啤酒和饮料,一共花了82.3元。
我们还知道他买的啤酒比饮料的数量少,请你计算他买了几罐啤酒。
注意:答案是一个整数。请通过浏览器提交答案
不要书写任何多余的内容(例如:写了饮料的数量,添加说明文字等)。

这道题是送分题,很多同学用通过暴力破解法这种方法实现的:

public class 浮点数1_啤酒和饮料 {
    public static void main(String[] args) {
        for (int a = 0; a < 100; a++)  //a 是啤酒数量,b是饮料的数量,假设它们的取值范围都在0 ~ 100
        {
            for (int b = 0; b < 100; b++) {
                if (a * 2.3 + b * 1.9 == 82.3 && a < b)
                    System.out.println(a + "," + b);
            }
        }
    }
}

只不过,犯了一个大忌——两个浮点数之间不能用“==”来判断是否相等。因为浮点数在计算式内部是采用二进制的方式来表示。因此在计算机中0.1+0.2不是等于0.3,而是等于“0.30000000000000004”(不信自己去敲一敲)。这道题能算出结果算是你运气好。
既然这样,那我们如何来判断浮点数是否相等呢?
要判断浮点数是否相等,则a-b的绝对值无限接近一个非常小的值。
|a - b| < set,一般set=1E-6(科学计数法,1*10的负6次方)即可。
由此可以这样实现:

public class 浮点数1_啤酒和饮料 {
    public static void main(String[] args) {
        for (int a = 0; a < 100; a++)  //a 是啤酒数量,b是饮料的数量,假设它们的取值范围都在0 ~ 100
        {
            for (int b = 0; b < 100; b++) {
                if (Math.abs(a * 2.3 + b * 1.9 - 82.3) < 1E-10 && a < b)
                    System.out.println(a + "," + b);
            }
        }
    }
}

由于题目给的这些浮点数都保留一位小数,则可以把所有数值都乘以10,变成整数来全等判断:

public class 浮点数1_啤酒和饮料 {
    public static void main(String[] args) {
        for (int a = 0; a < 100; a++)  //a 是啤酒数量,b是饮料的数量,假设它们的取值范围都在0 ~ 100
        {
            for (int b = 0; b < 100; b++) {
                if (a * 23 + b * 19 == 823 && a < b)
                    System.out.println(a + "," + b);
            }
        }
    }
}

使用整数进行全等判断,比浮点数安全多了。

海盗问题

有一群海盗(不多于20人),在船上比拼酒量。过程如下:打开一瓶酒, 所有在场的人平分喝下,有几个人倒下了。再打开一瓶酒平分,又有倒下的,再次重复...... 直到开了第4瓶酒,坐着的已经所剩无几,海盗船长也在其中。当第4瓶酒平分喝下后,大家都倒下了。等船长醒来,发现海盗船搁浅了。他在航海日志中写到:“......昨天,我正好喝了一瓶.......奉劝大家,开船不喝酒,喝酒别开船......”
请你根据这些信息,推断开始有多少人,每一轮喝下来还剩多少人。
如果有多个可能的答案,请列出所有答案,每个答案占一行。
格式是:人数,人数,...
例如,有一种可能是:20,5,4,2,0

思路:这道题关键是船长的这句话,“昨天,我正好喝了一瓶”,船上打开了4瓶酒,每瓶酒向没醉的人进行平分。所以,由题意可得,每次平分的酒量相加为1。
代码如下:

public class 浮点数2_海盗问题 {
    public static void main(String[] args) {
        int a, b, c, d;  //每一轮剩下的人
        for (a = 20; a >= 1; a--)
            //第一轮,海盗的人不多于20人,但至少会有一人
            for (b = a - 1; b >= 1; b--)
                //每一轮都有人倒下,因此第二轮肯定比第一轮a的人数少
                for (c = b - 1; c >= 1; c--)
                    //第三轮人数比第二轮少,但至少有一人
                    for (d = c - 1; d >= 1; d--) {
                        //第四轮人数比第三轮少,但至少有一人
                        //船长四轮都喝了,每轮都是平分的酒,一共喝了一瓶
                        if (1.0 / a + 1.0 / b + 1.0 / c + 1.0 / d == 1.0)
                            System.out.println(a + "," + b + "," + c + "," + d);
                    }
    }
}

注意:判断式内一定是(1.0/a+1.0/b+1.0/c+1.0/d==1.0),如果是(1/a+1/b+1/c+1/d==1),由于1/a是整型,所以1/a为0,不是小数。
但是,上面的代码忽略了“两个浮点数之间不能用全等来判断是否相等。”这个易错点。

修改的代码如下:

public class 浮点数2_海盗问题 {
    public static void main(String[] args) {
        int a, b, c, d;  //每一轮剩下的人
        for (a = 20; a >= 1; a--)
            //第一轮,海盗的人不多于20人,但至少会有一人
            for (b = a - 1; b >= 1; b--)
                //每一轮都有人倒下,因此第二轮肯定比第一轮a的人数少
                for (c = b - 1; c >= 1; c--)
                    //第三轮人数比第二轮少,但至少有一人
                    for (d = c - 1; d >= 1; d--) {
                        //第四轮人数比第三轮少,但至少有一人
                        //船长四轮都喝了,每轮都是平分的酒,一共喝了一瓶
                        if (Math.abs(1.0 / a + 1.0 / b + 1.0 / c + 1.0 / d - 1.0) < 1E-10)
                            System.out.println(a + "," + b + "," + c + "," + d);
                    }
    }
}

这道题,我们还有另一个判断的方式,就是在(1/a+1/b+1/c+1/d==1)中,每项分别乘以(a * b * c * d)
修改的代码如下:

public class 浮点数2_海盗问题 {
    public static void main(String[] args) {
        int a, b, c, d;  //每一轮剩下的人
        for (a = 20; a >= 1; a--)
            //第一轮,海盗的人不多于20人,但至少会有一人
            for (b = a - 1; b >= 1; b--)
                //每一轮都有人倒下,因此第二轮肯定比第一轮a的人数少
                for (c = b - 1; c >= 1; c--)
                    //第三轮人数比第二轮少,但至少有一人
                    for (d = c - 1; d >= 1; d--) {
                        //第四轮人数比第三轮少,但至少有一人
                        //船长四轮都喝了,每轮都是平分的酒,一共喝了一瓶
                        if (b * c * d + a * c * d + a * b * d + a * b * c == a * b * c * d)
                            System.out.println(a + "," + b + "," + c + "," + d);
                    }
    }
}

四舍六入五成双

Java舍入方式叫“四舍六入五成双”
规则:
(1)被修约的数字小于5时,该数字舍去;
(2)被修约的数字大于5时,则进位;
(3)被修约的数字等于5时,要看5前面的数字,若是奇数则进位,若是偶数则将5舍掉,即修约后末尾数字都成为偶数;若5的后面还有不为“0”的任何数,则此时无论5的前面是奇数还是偶数,均应进位。

举例,用上述规则对下列数据保留3位有效数字:
9.8249=9.82, 9.82671=9.83
9.8350=9.84, 9.8351 =9.84
9.8250=9.82, 9.82501=9.83
从统计学的角度,“四舍六入五成双”比“四舍五入”要科学,在大量运算时,它使舍入后的结果误差的均值趋于零,而不是像四舍五入那样逢五就入,导致结果偏向大数,使得误差产生积累进而产生系统误差,“四舍六入五成双”使测量结果受到舍入误差的影响降到最低。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容