动态输出n位小数——满满都是坑!

news2024/10/5 20:20:58

【题目描述】

输入正整数abc,输出a/b的小数形式,精确到小数点后c位。a,b ≤10^6 ,c≤100。输入包含多组数据,结束标记为abc=0。

【样例输入】

1 6 4

0 0 0

【样例输出】

Case 1: 0.1667

【题目来源】

刘汝佳《算法竞赛入门经典  第2版》习题2-5 分数化小数(decimal)

【解析】

这道题很简单呀!

等等,以前都是题目中明确给出保留几位小数,比如要求保留3位小数,咱们就可以:

printf(“%.3f”, a/b);

本题要保留的小数位数是在程序运行时指定的,取决于用户输入的c,这该怎么办呢?难不成要写成这样:

printf(“%.%df”, c, a/b);

实际测试完全行不通,看来格式说明符是不能嵌套的。这其实很好理解,如果支持嵌套,不光看起来乱,还会导致歧义。比如%%df,按理%%应解释为转义字符,用来表示字符“%”。

一、用系统函数动态输出n位小数

1.C语言版

这里涉及一个新的语法知识点,要实现按变量的值动态输出小数位数,就要把代码改成这样子:

printf(“%.*f”, c, a/b);

*和f一样,也是一个占位符,起占位作用,它表示从参数中取一个整数值来作为浮点数的精度。

学会了这种操作,代码马上呼之欲出:

#include<stdio.h>
int main(){
    int a, b, c, kase=0;
    while(scanf("%d%d%d", &a, &b, &c)==3 && a*b*c){
        double f = (double)a/b;
        printf("Case %d: %.*f\n", ++kase, c, f);
    }
    return 0;
}

输入样例测试也满全符合,是不是大功告成了呢?

2. C++版

除了上面的C语言版,也可以使用纯C++语法动态输出小数位数(语法非常麻烦)。

#include <iostream>
#include <iomanip> // 包含 setprecision 的头文件
using namespace std;
int main() {
    int a, b, c, kase=0;
    while(scanf("%d%d%d", &a, &b, &c)==3 && a*b*c){
        double f = (double)a/b;
        cout << "Case " << ++kase << ": " << fixed << setprecision(c) << f << endl;
    }
    return 0;
}

遗憾的是,咱们费了半天劲儿,上面的面代码却都是错误的。

重点就在于题目要求c≤100,如果输入1 6 100,马上就会发现输出结果不正确。

测试是非常重要的,尤其是边界数据的测试更为重要。

因为double的有效精度只有16位,因而用printf根本无法有效输出100位小数。

怎么办呢?自己动手,丰衣足食。

二、自己动手算小数

咱们要用程序模拟小数除法运算,想想小学时学的运算规则:每次求出的余数后添0,然后继续除。比如28÷16:

算法可以描述为:

①求商的整数部分。

②求商的小数部分:重复将余数乘10继续除。

这就完了吗?别忘了“精确到小数点后c位”的意思?最后一位输出的小数需要四舍五入。

代码如下:

#include<stdio.h>
int main(){
    int a, b, c, kase=0;
    while(scanf("%d%d%d", &a, &b, &c)==3 && a*b*c){
        //输出小数点前的内容
        printf("Case %d: %d.", ++kase, a/b);

        //输出小数点后的c-1位
        a=a%b;
        for(int i=1; i<=c-1; i++){
            a*=10;
            printf("%d", a/b);
            a = a%b; //获取第i位运算后的余数
        }

        //输出第c位小数,四舍五入
        a*=10;
        printf("%d", a/b + 10*(a%b)/b/5);

        printf("\n");
    }
    return 0;
}

四舍五入部分当然也可以用If语句判断第c+1位小数的值是否大于等于5,这里用了一个巧算,用n/5即可实现当n≥5时,结果为1。

这回终于结束了吧!

No,No,No,客官即将迎来本题的最大深坑。

如果输入下面的数据,就知道上面的代码问题出在哪了。

999 1000 2

9999 1000 2

输出结果:

因为小数部分有一连串的9,进位会导致前面的小数甚至整数全部改变,因而按照上面的代码就会输出错误结果。

如果给咱9999/1000这道算术题,让咱保留两位小数,咱肯定不会算错。但是让咱设计保留2位小数的算法,就非常容易忽略这种情况。前者是看到某种情形,想到对应规则,后者是想到所有情形,想到对应规则,难度不可同日而语。

所以算法设计必须要穷尽所有可能性,遗漏任何一种情形都会导致出错。对于数据来讲,最容易被忽略的就是边界数据。

比如本题,小数位数100位是边界,最后一位小数要四舍五入是边界,9进位会变成0也是边界(9是最大数字)。因此,对于任何类型的数据,一定要养成思考边界、测试边界的习惯。

三、用数组解决999式进位问题

要解决这个问题,就需要用到数组,把每位小数都存到数组中,再根据各位小数值及是否要进位重新修正每位小数的值。

代码如下:

#include<stdio.h>
int main(){
    int a, b, c, point, d[105], kase=0;
    while(scanf("%d%d%d", &a, &b, &c)==3 && a*b*c){
        //求出小数点后的c+1位
        int r=a%b;
        for(int i=1; i<=c+1; i++){
            r*=10;
            d[i] = r/b;
            r%=b; //获取第i位运算后的余数
        }

        //根据是否进位修正各位小数
        d[0] = 0; //保存小数到整数的进位
        if(d[c+1] >= 5){
            for(int i=c; i>=0; i--){
                if(9 == d[i]){
                    d[i] = 0;
                } else{
                    d[i] += 1;
                    break;
                }
            }
        }

        //输出小数点前的内容
        printf("Case %d: %d.", ++kase, a/b + d[0]);
        
        //输出小数部分
        for(int i=1; i<=c; i++){
            printf("%d", d[i]);
        }
        printf("\n");
    }
    return 0;
}

需要说明的是,本题是第2章习题,此章节还没学到数组,但这道题目前老金只会用数组求解。如有高人知道不用数组的解法,还望指点一二!

最后总结一下,这道题非常容易出错,它有三大神坑:

①用printf函数最多只能输出16位有效小数,无法输出100位,必须要自己模拟除法运算求小数。

②最后一位小数需要根据下一位小数四舍五入。

③最后一位小数如果是9,在四舍五入时会导致前面的小数发生变化,如果有一连串的9,可能会使所有小数甚至整数部分都产生变化。这是本题最大的坑,可谓神之一坑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1578057.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2012年认证杯SPSSPRO杯数学建模D题(第二阶段)人机游戏中的数学模型全过程文档及程序

2012年认证杯SPSSPRO杯数学建模 D题 人机游戏中的数学模型 原题再现&#xff1a; 计算机游戏在社会和生活中享有特殊地位。游戏设计者主要考虑易学性、趣味性和界面友好性。趣味性是本质吸引力&#xff0c;使玩游戏者百玩不厌。网络游戏一般考虑如何搭建安全可靠、丰富多彩的…

[开源] 基于GRU的时间序列预测模型python代码

基于GRU的时间序列预测模型python代码分享给大家&#xff0c;记得点赞哦 #!/usr/bin/env python # coding: utf-8import time time_start time.time() import numpy as np import matplotlib.pyplot as plt import pandas as pd import math from keras.models import Sequent…

免费分享一套微信小程序在线订餐(点餐)配送系统(SpringBoot+Vue),帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序在线订餐(点餐)配送系统(SpringBootVue)&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序在线订餐(点餐)配送系统(SpringBootVue) Java毕业设计_哔哩哔哩_bilibili【免费】微信小程序在…

两相欠压继电器 WY-35A3 额定输入电压100V 导轨安装 JOSEF约瑟

系列型号&#xff1a; WY-35A4电压继电器&#xff1b;WY-35B4电压继电器&#xff1b; WY-35C4电压继电器&#xff1b;WY-35D4电压继电器&#xff1b; WY-35A4D电压继电器&#xff1b;WY-35A4T电压继电器&#xff1b; WY-35B4D电压继电器&#xff1b;WY-35B4T电压继电器&#xf…

希亦、添可、追觅洗地机深入对比,哪个更胜一筹?选择不再迷茫

洗地机不仅能快速打扫地面&#xff0c;省时又省力&#xff0c;还能把室内弄得干干净净的&#xff0c;用起来感觉特舒服。但是面对目前市面上几百个型号的洗地机&#xff0c;在观望洗地机的家庭&#xff0c;大多数都是不确定哪款洗地机适合自己&#xff0c;今天笔者就带来了三款…

Flink内存模型

1、Flink进程内存模型 配置项 TaskManager 配置参数 JobManager 配置参数 Flink 总内存taskmanager.memory.flink.sizejobmanager.memory.flink.size进程总内存taskmanager.memory.process.sizejobmanager.memory.process.size 2、Task Managers内存模型 组成部分 配…

JSON字符串中获取一个特定字段的值

JSON字符串中获取一个特定字段的值 一、方式一&#xff0c;引用gson工具二、方式二&#xff0c;使用jackson三、方式三&#xff0c;使用jackson转换Object四、方式四&#xff0c;使用hutool&#xff0c;获取报文数组数据 一、方式一&#xff0c;引用gson工具 测试报文&#xf…

八字测算qq手机号码生辰吉凶81数理测算数据

#小李子9479# 首先&#xff0c;要有81数理的数据&#xff0c;经过多方搜集&#xff0c;终于整理成下面sql数据表。 **注意&#xff0c;以阳历&#xff0c;即农历日期为准。** 根据生日年月日时计算81数理钩子数&#xff0c; 年&#xff0c;月&#xff0c;日&#xff0c;时分…

使用 Python 批量提取 Excel 中的图片(提供工具下载链接)

本文收录于《Python入门核心技术》专栏&#xff0c;专栏总目录&#xff1a;点这里&#xff0c;订阅后可阅读专栏内所有文章。 大家好&#xff0c;我是水滴~~ 本文主要讲解如何利用 Python 来批量提取 Excel 中的图片&#xff0c;分别保存到目录中。并将程序打包成可执行文件&am…

【MATLAB源码-第180期】基于matlab的PTS,SLM,CPFilter三种降低OFDM系统的PAPR仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. 限幅和滤波&#xff08;Clipping and Filtering&#xff09; 原理简介 限幅和滤波是一种基础且直观的方法&#xff0c;用于降低OFDM信号的PAPR。在限幅阶段&#xff0c;信号的幅度在达到设定阈值时会被削减&#xff0c;…

《springcloud alibaba》 四 seata安装以及使用

目录 准备调整db配置准备创建数据库 seata配置nacos配置confi.txt下载向nacos推送配置的脚本 启动seata新建项目order-seata项目 订单项目数据库脚本pom.xmlapplication.yml启动类实体类dao类service类controller类feign类mapper类 stock-seata 库存项目数据库脚本pom.xmlappli…

高效解决Ubuntu Server 18.04.1 LTS 64bit更新gdb8.1.1到gdb12.1

文章目录 问题解决步骤 问题 因为需要用到gdb一些指令&#xff0c;但是gdb8.x好像存在普遍的问题&#xff0c;实现不了某些指令&#xff0c;比方说set detach-on-fork on&#xff0c;升级版本也没有比较好的教程 经过我不断的试错&#xff0c;我终于升级成功了&#xff01;&a…

Qt使用QWidget重绘实现圆环形渐变色进度条(支持不确定进度模式)

效果如下&#xff1a; 从纯竖直方向顶部蓝色到底部青色的渐变。 从左上角偏左45到右下角偏右45的蓝色到青色渐变。 从左上角偏左22.5到右下角偏右22.5的蓝色到青色渐变。&#xff08;这个角度渐变最好看&#xff09; 可以选择添加背景图片 支持两种模式&#xff1a;正常进度模…

【完全背包求方案数问题】AcWing1023.买书(赋练习题目)

【题目链接】活动 - AcWing 输入样例1&#xff1a; 20输出样例1&#xff1a; 2输入样例2&#xff1a; 15输出样例2&#xff1a; 0输入样例3&#xff1a; 0输出样例3&#xff1a; 1 【代码】 //1023.买书——完全背包问题#include<bits/stdc.h>using namespace st…

我去,PMP原来不是所有人都能报!

很多人可能觉得PMP的报名条件很复杂&#xff0c;又是经验要求&#xff0c;又是学历要求的&#xff0c;网络上关于PMP报名条件说的层出不穷&#xff0c;今天给大家统一一下&#xff0c;报名PMP究竟需要什么条件&#xff1a; 官方报考条件&#xff1a; 一、报名考生必须具备35小…

【I2C总线驱动】

一、I2C总线背景知识 SOC芯片平台的外设分为&#xff1a; 一级外设&#xff1a;外设控制器集成在SOC芯片内部二级外设&#xff1a;外设控制器由另一块芯片负责&#xff0c;通过一些通讯总线与SOC芯片相连 Inter-Integrated Circuit&#xff1a; 字面意思是用于“集成电路之间…

多叉树题目:子树中标签相同的结点数

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;子树中标签相同的结点数 出处&#xff1a;1519. 子树中标签相同的结点数 难度 5 级 题目描述 要求 给你一个树&#xff08;即一个连通的无向无环图…

QT 使用redis ,连接并使用

一.redis安装 链接&#xff1a;https://pan.baidu.com/s/17fXKOj5M4VIypR0y5_xtHw 提取码&#xff1a;1234 1.下载得到文件夹如图 course_redis为安装包。 2.启动Redis服务 把安装包解压到某个路径下即可。 打开cmd窗口&#xff0c;切换到Redis安装路径&#xff0c;输入 r…

飞企互联-FE企业运营管理平台 druid路径 弱口令漏洞复现

0x01 产品简介 飞企互联-FE企业运营管理平台是一个基于云计算、智能化、大数据、物联网、移动互联网等技术支撑的云工作台。这个平台可以连接人、链接端、联通内外,支持企业B2B、C2B与O2O等核心需求,为不同行业客户的互联网+转型提供支持。 0x02 漏洞概述 飞企互联-FE企业…

AI编程005/ 逆向生成mysql的建表语句

1/ 通过insert into 语句生成建表语句 有些时候我们能获取到表的insert语句&#xff0c;但是没有表结构。我们可以借助AI工具&#xff0c;让其逆向生成mysql的建表语句。 提示词如下&#xff1a; 根据下面的SQL语句&#xff0c;逆向生存mysql的建表语句&#xff0c;每个字段…