进制转换在C/C++/Java/Kotlin中的应用(详细版)(上)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 进制转换在C/C++/Java/Kotlin中的应用(详细版)

// 清除标志位 为了得到正确的can_id,需要在解析之前清除可能设置的标志位。通过使用& 0x1FFFFFFF来实现,这个操作会清除can_id的高3位,确保结果得到的是纯粹的ID。

uint32_t clean_can_id = frame.can_id & 0x1FFFFFFF;

因为上面的问题 我不理解 所以来学习进制转换的应用 , 进制转换非常常见 , 如果你搞底层 这个是必须会的 , 我工作中也经常碰到 每次看到都非常头疼 , 学完就忘 然后大半年碰一次。进制转换不难理解的 , 配合计算器程序员模式 学习起来很快 , 难就难在很难记忆 , 这一次来系统的学习下。

一般用于嵌入式 , Driver 看datasheet 寄存器计算都有可能会碰见。C/C++出现的次数比较多。Java/kotlin网络相关的内容也比较常见。

进制转换在编程中的重要性

进制转换是指将一个数从一种进制表示方式转换 (计算)为另一种进制 (数)表示方式。例如,将十进制数10转换为二进制数1010,或者将十六进制数FF转换为十进制数255。在编程中,经常需要处理不同进制的数,因为计算机内部使用二进制来存储和处理数据,一般使用十进制来输入和输出数据。像我们搞开发的,我们还需要使用八进制或十六进制来表示数据,例如文件权限、寄存器/内存地址、颜色值等。掌握不同进制之间的转换方法,可以帮助我们更好地理解计算机的工作原理。

进制基础

二进制、八进制、十进制和十六进制的概念

不同的表示方法有不同的优点和缺点。二进制最符合计算机的逻辑电路设计,因为它只需要两种状态(开或关)来表示一个位(bit)。但是二进制表示起来比较冗长,不方便阅读和记忆。十进制最符合人脑的计数习惯,因为它与我们的手指数目相对应。但是十进制与计算机的二进制不兼容,需要进行转换。八进制和十六进制是一种折中的方案,它们可以方便地与二进制对应,每个八进制数字对应3个二进制位,每个十六进制数字对应4个二进制位。同时,它们也可以缩短表示长度,提高可读性。

进制名称 符号/数字 符号/数字数量 与二进制的关系 优点 缺点
二进制 (Binary) 0,1 2 直接对应 符合计算机的逻辑电路设计 表示冗长,不方便人类阅读和记忆
八进制 (Octal) 0-7 8 每数字对应3个二进制位 可以方便地与二进制对应,缩短表示长度 不如十进制直观,但比二进制更简洁
十进制 (Decimal) 0-9 10 不直接对应 与人类的计数习惯相符,与手指数目相对应 与计算机的二进制不兼容,需要转换
十六进制 (Hexadecimal) 0-9, A-F 16 每数字对应4个二进制位 可以方便地与二进制对应,缩短表示长度,提高可读性 不如十进制直观,但比二进制和八进制更简洁

不同进制之间的转换方法

不同进制之间的转换方法有两种:按权展开法除基取余法。按权展开法是将一个数从一种进制转换为十进制,除基取余法是将一个数从十进制转换为另一种进制。我们以二进制、八进制、十六进制为例,介绍这两种方法。

按权展开法

按权展开法的原理是将一个数按照其所在的位置(称为位权)乘以相应的基数(称为),然后求和。

进制转换的按权展开法是一个基于数的基数和权重来进行转换的方法。以下是一个简单的表格,展示了从其他进制转换到十进制的按权展开法:

进制 数字 权重 按权展开 二进制 a n a n − 1 … a 1 a 0 2 i a i × 2 i 八进制 b n b n − 1 … b 1 b 0 8 i b i × 8 i 十六进制 c n c n − 1 … c 1 c 0 1 6 i c i × 1 6 i

anan1a1a0bnbn1b1b0cncn1c1c02i8i16iai×2ibi×8ici×16i进制数字权重按权展开二进制𝑎𝑛𝑎𝑛−1…𝑎1𝑎02𝑖𝑎𝑖×2𝑖八进制𝑏𝑛𝑏𝑛−1…𝑏1𝑏08𝑖𝑏𝑖×8𝑖十六进制𝑐𝑛𝑐𝑛−1…𝑐1𝑐016𝑖𝑐𝑖×16𝑖

进制二进制八进制十六进制数字anan1a1a0bnbn1b1b0cncn1c1c0权重2i8i16i按权展开ai×2ibi×8ici×16i

(i) 是数字的位置,从右到左计数,从0开始。

  1. 二进制 (1011_2)

进制 数字 权重 按权展开 二进制 1 2 3 1 × 2 3 = 8 二进制 0 2 2 0 × 2 2 = 0 二进制 1 2 1 1 × 2 1 = 2 二进制 1 2 0 1 × 2 0 = 1 总和 8 + 0 + 2 + 1 = 1 1 10

1011232221201×23=80×22=01×21=21×20=18+0+2+1=1110进制数字权重按权展开二进制1231×23=8二进制0220×22=0二进制1211×21=2二进制1201×20=1总和8+0+2+1=1110

进制二进制二进制二进制二进制数字1011权重23222120总和按权展开1×23=80×22=01×21=21×20=18+0+2+1=1110

  1. 八进制 (52_8)

进制 数字 权重 按权展开 八进制 5 8 1 5 × 8 1 = 40 八进制 2 8 0 2 × 8 0 = 2 总和 40 + 2 = 4 2 10

5281805×81=402×80=240+2=4210进制数字权重按权展开八进制5815×81=40八进制2802×80=2总和40+2=4210

进制八进制八进制数字52权重8180总和按权展开5×81=402×80=240+2=4210

  1. 十六进制 (1A_{16})

进制 数字 权重 按权展开 十六进制 1 1 6 1 1 × 1 6 1 = 16 十六进制 A ( 10 ) 1 6 0 10 × 1 6 0 = 10 总和 16 + 10 = 2 6 10

1A(10)1611601×161=1610×160=1016+10=2610进制数字权重按权展开十六进制11611×161=16十六进制𝐴(10)16010×160=10总和16+10=2610

进制十六进制十六进制数字1A(10)权重161160总和按权展开1×161=1610×160=1016+10=2610

注意,在十六进制中,A,B,C,D,E,F分别表示10,11,12,13,14,15。

除基取余法

除基取余法的原理是将一个数不断地除以目标进制的基数,然后将余数倒序排列。例如,十进制数10要转换为二进制,可以不断地除以2,并记录余数。

10 ÷ 2 = 5 余 0 5 ÷ 2 = 2 余 1 2 ÷ 2 = 1 余 0 1 ÷ 2 = 0 余 1

10521÷2=5÷2=2÷2=1÷2=0010110÷2=5余05÷2=2余12÷2=1余01÷2=0余1

10521÷2=5÷2=2÷2=1÷2=00101

然后将余数倒序排列得到:

1 0 10 = 101 0 2 10_{10} =1010_21010=10102

类似地,十进制数83要转换为八进制,可以不断地除以8,并记录余数:

83 ÷ 8 = 10 余 3 10 ÷ 8 = 1 余 2 1 ÷ 8 = 0 余 1

83101÷8=10÷8=1÷8=032183÷8=10余310÷8=1余21÷8=0余1

83101÷8=10÷8=1÷8=0321

然后将余数倒序排列得到:

8 3 10 = 12 3 8 83_{10} =123_88310=1238

十进制数2748要转换为十六进制,可以不断地除以16,并记录余数:

2748 ÷ 16 = 171 余 12 171 ÷ 16 = 10 余 11 10 ÷ 16 = 0 余 10

274817110÷16=171÷16=10÷16=01211102748÷16=171余12171÷16=10余1110÷16=0余10

274817110÷16=171÷16=10÷16=0121110

然后将余数倒序排列得到:

274 8 10 = A B C 16 2748_{10} =ABC_{16}274810=ABC16

注意,在十六进制中,10,11,12,13,14,15分别用A,B,C,D,E,F表示。

C/C++/Java/Kotlin中的进制表示

在C/C++/Java/Kotlin等编程语言中,可以使用不同的方式来表示不同进制的数。一般来说,可以使用以下的规则:

  • 二进制数:在数前加上0b0B,表示该数是二进制数。例如,0b1010表示二进制数1010。
  • 八进制数:在数前加上0,表示该数是八进制数。例如,0123表示八进制数123。
  • 十进制数:直接写出数,不需要加任何前缀。例如,10表示十进制数10。
  • 十六进制数:在数前加上0x0X,表示该数是十六进制数。例如,0xABC表示十六进制数ABC。

C/C++/Java/Kotlin中进制的转换函数

在C/C++/Java/Kotlin等编程语言中,可以使用一些内置的或自定义的函数来实现不同进制之间的转换。这些函数可以分为两类:字符串转换函数整数转换函数

字符串转换函数是指将一个字符串(即一系列字符)按照指定的进制解析为一个整数。例如,将字符串"1010"按照二进制解析为整数10。这类函数通常有两个参数:一个是要转换的字符串,另一个是指定的进制。以下是一些常用的字符串转换函数:

  • C/C++中的[strtol]函数:该函数可以将一个字符串按照指定的进制(2到36之间)解析为一个长整型(long)数。例如:
#include <stdio.h>
#include <stdlib.h>
int main()
{
    char *s1 = "1010"; // 二进制字符串
    char *s2 = "123"; // 八进制字符串
    char *s3 = "ABC"; // 十六进制字符串
    long n1 = strtol(s1, NULL, 2); // 将二进制字符串转换为长整型
    long n2 = strtol(s2, NULL, 8); // 将八进制字符串转换为长整型
    long n3 = strtol(s3, NULL, 16); // 将十六进制字符串转换为长整型
    printf("%ld\n", n1); // 输出10
    printf("%ld\n", n2); // 输出83
    printf("%ld\n", n3); // 输出2748
    return 0;
}

  • Java中的[Integer.parseInt]函数:该函数可以将一个字符串按照指定的进制(2到36之间)解析为一个整型(int)数。例如:
public class Main {
    public static void main(String[] args) {
        String s1 = "1010"; // 二进制字符串
        String s2 = "123"; // 八进制字符串
        String s3 = "ABC"; // 十六进制字符串
        int n1 = Integer.parseInt(s1, 2); // 将二进制字符串转换为整型
        int n2 = Integer.parseInt(s2, 8); // 将八进制字符串转换为整型
        int n3 = Integer.parseInt(s3, 16); // 将十六进制字符串转换为整型
        System.out.println(n1); // 输出10
        System.out.println(n2); // 输出83
        System.out.println(n3); // 输出2748
    }
}
  • Kotlin中的[toInt]函数:该函数可以将一个字符串按照指定的进制(2到36之间)解析为一个整型(Int)数。例如:
fun main() {
    val s1 = "1010" // 二进制字符串
    val s2 = "123" // 八进制字符串
    val s3 = "ABC" // 十六进制字符串
    val n1 = s1.toInt(2) // 将二进制字符串转换为整型
    val n2 = s2.toInt(8) // 将八进制字符串转换为整型
    val n3 = s3.toInt(16) // 将十六进制字符串转换为整型
    println(n1) // 输出10
    println(n2) // 输出83
    println(n3) // 输出2748
}

整数转换函数是指将一个整数按照指定的进制格式化为一个字符串。例如,将整数10按照二进制格式化为字符串"1010"。这类函数通常有两个参数:一个是要转换的整数,另一个是指定的进制。以下是一些常用的整数转换函数:

  • C/C++中的[itoa]函数:该函数可以将一个整数按照指定的进制(2到36之间)格式化为一个字符串。该函数不是标准库函数,而是一些编译器提供的扩展函数。例如:
#include <stdio.h>
#include <stdlib.h>
int main()
{
    int n1 = 10; // 十进制数
    int n2 = 83; // 十进制数
    int n3 = 2748; // 十进制数
    char s1[10]; // 存储二进制字符串的数组
    char s2[10]; // 存储八进制字符串的数组
    char s3[10]; // 存储十六进制字符串的数组
    itoa(n1, s1, 2); // 将十进制数转换为二进制字符串
    itoa(n2, s2, 8); // 将十进制数转换为八进制字符串
    itoa(n3, s3, 16); // 将十进制数转换为十六进制字符串
    printf("%s\n", s1); // 输出1010
    printf("%s\n", s2); // 输出123
    printf("%s\n", s3); // 输出ABC
    return 0;
}
  • Java中的[Integer.toString]函数:该函数可以将一个整数按照指定的进制(2到36之间)格式化为一个字符串。例如:
public class Main {
    public static void main(String[] args) {
        int n1 = 10; // 十进制数
        int n2 = 83; // 十进制数
        int n3 = 2748; // 十进制数
        String s1 = Integer.toString(n1, 2); // 将十进制数转换为二进制字符串
        String s2 = Integer.toString(n2, 8); // 将十进制数转换为八进制字符串
        String s3 = Integer.toString(n3, 16); // 将十进制数转换为十六进制字符串
        System.out.println(s1); // 输出1010
        System.out.println(s2); // 输出123
        System.out.println(s3); // 输出ABC
  • Kotlin中的[toString]函数:该函数可以将一个整数按照指定的进制(2到36之间)格式化为一个字符串。例如:
fun main() {
    val n1 = 10 // 十进制数
    val n2 = 83 // 十进制数
    val n3 = 2748 // 十进制数
    val s1 = n1.toString(2) // 将十进制数转换为二进制字符串
    val s2 = n2.toString(8) // 将十进制数转换为八进制字符串
    val s3 = n3.toString(16) // 将十进制数转换为十六进制字符串
    println(s1) // 输出1010
    println(s2) // 输出123
    println(s3) // 输出ABC
}


进制转换在C/C++/Java/Kotlin中的应用(详细版)(下)+https://developer.aliyun.com/article/1489623

相关文章
|
6天前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
|
15天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
8天前
|
SQL Java 数据库连接
从理论到实践:Hibernate与JPA在Java项目中的实际应用
本文介绍了Java持久层框架Hibernate和JPA的基本概念及其在具体项目中的应用。通过一个在线书店系统的实例,展示了如何使用@Entity注解定义实体类、通过Spring Data JPA定义仓库接口、在服务层调用方法进行数据库操作,以及使用JPQL编写自定义查询和管理事务。这些技术不仅简化了数据库操作,还显著提升了开发效率。
20 3
|
14天前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
14天前
|
存储 Kotlin
正则表达式在Kotlin中的应用:提取图片链接
正则表达式在Kotlin中的应用:提取图片链接
|
14天前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
14天前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
|
16天前
|
SQL Java 数据库连接
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率。本文介绍了连接池的工作原理、优势及实现方法,并提供了HikariCP的示例代码。
30 3
|
16天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
33 2
WK
|
16天前
|
安全 Java 编译器
C++和Java哪个更好用
C++和Java各具优势,选择取决于项目需求、开发者偏好及目标平台特性。C++性能出色,适合游戏、实时系统等;Java平台独立性强,适合跨平台、安全敏感应用。C++提供硬件访问和灵活编程范式,Java有自动内存管理和丰富库支持。两者各有千秋,需根据具体需求选择。
WK
12 1