【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;
}

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


相关文章
|
3月前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
98 4
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
87 5
|
2月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
2月前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
61 1
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
80 1
|
2月前
|
网络协议 物联网 数据处理
C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势
本文探讨了C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势。文章详细讲解了使用C语言实现网络通信程序的基本步骤,包括TCP和UDP通信程序的实现,并讨论了关键技术、优化方法及未来发展趋势,旨在帮助读者掌握C语言在网络通信中的应用技巧。
66 2
|
2月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
2月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
3月前
|
程序员 C语言
【C语言】LeetCode(力扣)上经典题目
【C语言】LeetCode(力扣)上经典题目
|
3月前
|
Java Unix Linux
1.3 C语言的应用范围
C语言自20世纪80年代以来一直是主流编程语言,适用于小型计算机、个人电脑及大型机。因其高效紧凑且易于修改和移植,广泛用于软件开发。尽管后来C++和JAVA流行起来,但C语言仍然是软件行业核心,并在嵌入式系统、科学编程和操作系统开发如Linux中扮演重要角色。即使到现在,掌握C语言仍是一项重要技能。不是必须得是计算机专家才能使用C语言,学习C语言同时也能学到很多C++的知识。
80 8

热门文章

最新文章