【C语言】输入一个十进制正整数,将它对应的二进制数的各位逆序,形成新的十进制数输出。题目分析及拓展应用。

简介: 【C语言】输入一个十进制正整数,将它对应的二进制数的各位逆序,形成新的十进制数输出。题目分析及拓展应用。

一.题目及答案

如图,题目及答案如下

该程序完整代码如下(需要可自由复制):

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
    int x, y, t;
    scanf("%d", &x);
    y = 0;
    while (x)
    {
        t = x%2;
        y =2*y+t;
        x/=2;
    }
    printf("%d\n", y);
    return 0;
}

二.对该程序的分析及详解

以下是对该程序的分析:

先来看题目:

输入一个十进制正整数,将它对应的二进制数各位逆序,形成新的十进制数输出。

如:13-- > 1101-- > 1011-- > 11

如:10-- > 1010-- > 0101-- > 5

也即,我们的目标是十进制整数转换二进制,再将二进制逆序,再将逆序后的二进制转换十进制

下面详解一下该题目的思路:

我们可以采用循环的形式,先将该数字上的二进制数一个一个剥下来,再倒序着一位一位安上去,流程大概如图:

将数字剥下来我们比较好理解,无非是剥几进制就给数字一直%几就行,比如该题剥二进制,那我们就可以先用一个变量t来记录下每一位剥下的数字,即:

t=x%2;

接下来问题是怎样将剥下来的数字安进新数字的中未被占用的首位了,显然我们现在是无法知道新输入的数的二进制最高位的权重的,虽然可以在最开始使用循环计算该数字的最高位,但这样有些太麻烦,因此我们不能一开始就将剥下来的末尾数字放在首位,只能采取先放在末位,再逐级向首位移动的方法,代码实现如下:

y=2*y+t;

这行代码妙在不需要知道最高权重直接从末位向前递补除了第一次,剩下的每次随着每补进来一位数,前面的所有位数的权重都会+1,下面给大家画图演示一下:

理解了这步,整个题目的思路也就分析完了。

接下来我们由此再拓展一些该思路的其他应用思路。


发现有很多朋友对"y=y*2+t"这条语句有些感到疑惑,所以我把这期间和一些朋友交流的过程贴在这里,希望可以帮助到更多新来的朋友:

这个是我手画的循环图示:

 

这个是方法来源:十进制转换N进制的基数乘除法

如果还是很难理解,那不妨先想像一个十进制数"123456"是如何通过%10取下一位,然后通过"y=y*10+t"这个公式一步一步转换到"654321"的:

可能我在这里讲的还不是非常清楚,还有疑问的朋友欢迎私信我一起交流!


三.对该题的举一反三

接下来我们会分别将前面题目的”剥数字“思想延申应用至两种题目中:

1.将十进制数对应的n进制数各位逆序,形成新的十进制输出。

2.将十进制数转换成相应的n进制数输出

1.将十进制数对应的n进制数各位逆序,形成新的十进制输出

如题:

输入一个十进制正整数,将它对应的8进制数的各位逆序,形成新的十进制数输出。

如:13-- > 15-- > 51-- > 41

如:10-- > 12-- > 21-- > 17

通过前面2进制的例子,这道题我们很好就理解了,无非刚才是剥二进制数,现在改成剥八进制数,再给前面所有的数乘以8进制的权重,即*8即可。代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
    int x, y, t;
    scanf("%d", &x);
    y = 0;
    while (x)
    {
        t = x%8;
        y =8*y+t;
        x/=8;
    }
    printf("%d\n", y);
    return 0;
}

在vs2022中尝试运行一下:


再看下一题:

这道题同理,可以理解为把十进制的每位剥下来逆序安上再输出即可:

完整代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
    int x, y, t;
    scanf("%d", &x);
    y = 0;
    while (x)
    {
        t = x%10;
        y =10*y+t;
        x/=10;
    }
    printf("%d\n", y);
    return 0;
}

在vs2022测试运行结果:


综上所述,要转二进制逆序就%2,/2,乘2的权重;

转八进制逆序就%8,/8,乘8的权重;

转十进制就%10,/10,乘10的权重;

转十六进制逆序就%16,/16,乘16的权重。


2.将十进制数转换成相应的n进制数输出

我们常常碰到题目让我们将10进制数转换成2进制或8进制等n进制,这样的题目我们完全可以照搬上面的思路再稍加修改就可以。

在转换的时候,我们先按目标进制把每一位%下来(比如要转换成二进制就是%2),但在安放的时候统一给每一位乘以10的权重,就可以打印出一个看起来像二进制的十进制数了。

但是要注意,我们刚才转换过来的数是逆序安放上去的,所以如果直接%上10的权重会得到逆序的二进制数,vs2022环境演示如下:

不过没关系,这时候我们只需要在此基础上再逆序一遍得到的数字就可以了,即多加一个while循环:(该演示非最终版本

完整代码如下:(非最终版本

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  int x = 0;
  int y = 0;
  int t = 0;
  scanf("%d", &x);
  while (x)
  {
    t = x % 2;
    y = y * 2 + t;
    x /= 2;
  }
  while (y)
  {
    t = y % 2;
    x = x * 10 + t;
    y /= 2;
  }
  printf("%d", x);
  return 0;
}

注意!如果就这样单纯的逆序两遍的话该程序就会存在一个bug,那就是如果该十进制数转换目标进制后恰好是以0结尾的,那么末位的0就会丢失,如:

在此感谢一下我的好兄弟(这是他的博客主页),帮助我解决了这个bug。其实想明白后这里的问题很简单,给大家画个图讲解一下:

现在问题的原因就一目了然了,因为第二次转置时十进制中原本的末位0变成了前导0,因此用y当第二次循环的结束标志时,程序会因为无法继续计算前导0提前终止循环,导致末尾0丢失

搞清楚了原因,解决办法也非常简单,我们只需要记下第一个while循环时循环的次数,然后在第二个while循环时保证和第一次循环循环同样的次数即可。

解决方法如下:我们在程序中设立计数变量count,然后第一个whlie循环每循环一次,就使count++,直到循环终止,然后将count作为第二个while循环运行的条件每循环一次count--,直到count减为0,循环终止。

完整代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  int x = 0;
  int y = 0;
  int t = 0;
  scanf("%d", &x);
  int count = 0;//创建计数变量count
  while (x)
  {
    t = x % 2;
    y = y * 2 + t;
    x /= 2;
    count++;//while每循环一次,count+1
  }
  while (count)//count为0时程序终止
  {
    t = y % 2;
    x = x * 10 + t;
    y /= 2;
    count--;//while每循环一次,count-1
  }
  printf("%d", x);
  return 0;
}

综上,当我们掌握了进制转换的思路后,就可以自己写一个小程序来将输入的十进制数按照需要转换成任何n进制数啦,如:




该小程序完整代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  int x = 0;
  int y = 0;
  int t = 0;
  printf("输入要转换的十进制数:>");
  scanf("%d", &x);
  int z = x;
  int n = 0;
  int count = 0;
  printf("输入想要转换的进制:>");
  scanf("%d", &n);
  while (x)
  {
    t = x % n;
    y = y * n + t;
    x /= n;
    count++;
  }
  while (count)
  {
    t = y % n;
    x = x * 10 + t;
    y /= n;
    count--;
  }
  printf("将%d转换成%d进制后的数字为:%d\n", z, n, x);
  return 0;
}

水平有限,欢迎各位大佬评论或私信我一起交流,学习,进步,谢谢大家!


相关文章
|
4月前
|
前端开发 C语言
C语言06-HelloWorld执行流程分析
C语言06-HelloWorld执行流程分析
C语言06-HelloWorld执行流程分析
|
1月前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
63 4
|
3月前
|
存储 C语言
【C语言】基础刷题训练4(含全面分析和代码改进示例)
【C语言】基础刷题训练4(含全面分析和代码改进示例)
|
1月前
|
程序员 C语言
【C语言】LeetCode(力扣)上经典题目
【C语言】LeetCode(力扣)上经典题目
ly~
|
1月前
|
网络协议 算法 关系型数据库
C语言的应用
C 语言因其高效性和对硬件的直接访问能力,在多个领域有广泛应用。在系统软件领域,它被用于开发操作系统(如 Unix 和 Linux 的内核)和嵌入式系统(如汽车电子控制系统)。在游戏开发中,C 语言常用于构建游戏引擎的底层部分(如 Unity 和 Unreal Engine 的核心模块)及性能要求高的独立游戏。此外,C 语言也用于数据库管理系统(如 MySQL 和 PostgreSQL 的核心功能)和网络编程(如 TCP/IP 协议栈和网络服务器的核心模块)。
ly~
35 3
|
1月前
|
Java Unix Linux
1.3 C语言的应用范围
C语言自20世纪80年代以来一直是主流编程语言,适用于小型计算机、个人电脑及大型机。因其高效紧凑且易于修改和移植,广泛用于软件开发。尽管后来C++和JAVA流行起来,但C语言仍然是软件行业核心,并在嵌入式系统、科学编程和操作系统开发如Linux中扮演重要角色。即使到现在,掌握C语言仍是一项重要技能。不是必须得是计算机专家才能使用C语言,学习C语言同时也能学到很多C++的知识。
49 8
|
2月前
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
|
2月前
|
存储 安全 C语言
C语言 二级指针应用场景
本文介绍了二级指针在 C 语言中的应用,
|
3月前
|
存储 缓存 编译器
【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)(下篇)
scanf处理⽤⼾输⼊的原理是,⽤⼾的输⼊先放⼊缓存,等到按下回⻋键后,按照占位符对缓存进⾏解读。 解读⽤⼾输⼊时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为⽌。
168 2
|
3月前
|
存储 C语言
【C语言篇】scanf和printf万字超详细介绍(基本加拓展用法)(上篇)
printf 的作⽤是将参数⽂本输出到屏幕。它名字⾥⾯的 f 代表 format (格式化),表⽰可以定制输出⽂本的格式。
80 1