关于作者
白晓明
宁夏图尔科技有限公司董事长兼CEO、坚果派联合创始人
华为HDE、润和软件HiHope社区专家、鸿蒙KOL、仓颉KOL
华为开发者学堂/51CTO学堂/CSDN学堂认证讲师
开放原子开源基金会2023开源贡献之星
公众号:开源开发者新视界(openwatcher)
1. 前言
计算机编程广袤领域中,进制转换犹如一座神秘而关键的桥梁,连接着数字世界的不同维度。它不仅仅是一项基础的技能,更是理解计算机内部运作机制、优化算法效率以及解决复杂问题的重要基石。
进制,作为数字的表达形式,在不同的场景中发挥着独特的作用。无论是二进制的简洁高效,用于计算机底层的运算和数据存储;还是十六进制的紧凑和直观,常用于表示内存地址和颜色编码;亦或者是我们日常生活中最熟悉的十进制,都各自有着不可替代的价值。
今天,让我们一同踏上这段充满探索与发现的旅程,揭开进制转换的神秘面纱。当然我们可以选择不同编程语言实现不同进制之间的转换,如C/C++,Java,JavaScript等。本章节主要以ArkTS语言和ArkUI框架为主,开发一款用于进制转换的HarmonyOS原生应用程序。
2. 进制转换初解
进制转换是计算机科学和数学中的一个基本概念,它涉及到将数字从一个数制(或基数)转换为另一个数制。最常见的进制包括二进制(0和1,基数为2)、八进制(0~7,基数为8)、十六进制(0~9和A~F,基数为16)。
2.1 工具界面和操作方式
1) 直观的布局
使用沿垂直方向布局容器Column、沿水平方向布局容器Row、文本显示Text、以及输入框TextInput组件构建进制转换页面。
2)简洁的输入框
TextInput({ placeholder : `请输入需要转换的二进制字符`, text: this.convert.getBinary() })
.layoutWeight(1)
.height('100%')
.placeholderFont({
size: 12
})
.borderRadius(8)
.showUnderline(true)
.underlineColor({
normal: Color.Orange,
typing: Color.Green,
error: Color.Red,
disable: Color.Gray
})
2.2 支持的进制类型
1)二进制使用场景
-
计算机内部表示:计算机中的所有信息,包括数据、指令和内存地址,都是以二进制形式存储和处理。
-
数据传输:在通信系统中,数据通常以二进制形式在设备和网络之间传输。
-
数字逻辑电路:在数字电子学中,逻辑门(如AND、OR、NOT等)和触发器都是以二进制逻辑为基础构建。
2)八进制使用场景
-
历史遗留:尽管在现代计算机系统中八进制的使用已经大大减少,但在早期计算机编程中,八进制曾用于表示文件权限(如Unix和Linux系统中的文件权限)。
-
简化二进制表示:由于每三位二进制数可以唯一地表示一个八进制数,因此八进制提供了一种比二进制更紧凑但比十进制更易于从二进制转换的表示方法。这在如手动计算或调试低级硬件时可能很有用。
3)十进制使用场景
-
日常生活:十进制是我们日常生活中最常用的数制,由0~9十个数字符号表示,可以方便地表示大多数日常计算和财务交易。
-
科学和工程:在科学和工程领域,十进制被广泛用于测量、计算和报告结果。
4)十六进制使用场景
-
计算机编程:十六进制在编程中非常常见,特别是在处理内存地址、颜色代码(如网页设计中的RGB值)和机器语言指令时。
-
颜色编码:在图形和网页设计中,颜色经常以十六进制形式表示。比如,在HTML和CSS中,颜色可以表示为六个十六进制数字(前两个表示红色、中间两个表示绿色、最后两个表示蓝色)。
3 进制转换的原理和算法
3.1 不同进制之间的转换规则
1)二进制与十进制的转换方法
-
二进制转十进制:位权相加法,例如二进制数1010转换为十进制数,从右向左依次将二进制数的每一位与2的幂相乘(从0开始,一次递增),然后将结果相加,如下图所示。
-
-
十进制转二进制:除2取余法,例如十进制数10,除2直到商为0时,从下往上读取余数得到二进制数1010,如下图所示。
-
2)八进制与十进制的转换方法
-
八进制转十进制:同样依据位权原理,八进制数的每一位乘以8的相应幂次然后相加。
-
十进制转八进制:除8取余法,直到商为0时,从下往上读取余数得到八进制。
3)十六进制与十进制的转换方法
-
十六进制转十进制:十六进制数中的A~F分表表示10~15,位权计算时同样乘以16的相应幂次,然后相加。
-
十进制转十六进制:除16取余法,若余数大于9则用A~F表示,从下往上读取余数得到十六进制。
4)二进制与八进制、十六进制的转换方法
-
二进制转八进制:每三位二进制可以转换一个八进制数,不够三位在左侧补零。
-
二进制转十六进制:每四位二进制数可以转换一个十六进制数,不够四位左侧补零。
-
反向转换:可以将八进制或十六进制数拆分为二进制。
3.2 算法的实现和优化
/**
* 将二进制转换为十进制数字
* @param binary
* @returns
*/
private binaryToDecimal(binary: string): number {
let decimal: number = 0;
// 通过位运算进行转换
for (let i = 0; i < binary.length; i++) {
decimal += parseInt(binary[i]) << (binary.length - i - 1);
}
return decimal;
}
/**
* 十进制转二进制
* @param decimal
* @returns
*/
private decimalToBinary(decimal: number): string {
let binary = "";
// 通过位运算进行转换
while (decimal > 0) {
binary = (decimal & 1) + binary;
decimal >>= 1;
}
return binary;
}
/**
* 八进制转十进制
* @param octal
* @returns
*/
private octalToDecimal(octal: string): number {
let decimal = 0;
// 通过乘法运算进行转换
for (let i = 0; i < octal.length; i++) {
decimal += parseInt(octal[i]) * Math.pow(8, octal.length - i - 1);
}
return decimal;
}
/**
* 将十进制数字转换为八进制字符串
* @param decimal
* @returns
*/
private decimalToOctal(decimal: number): string {
let octal: string = "";
// 通过取余和整除运算进行转换
while (decimal > 0) {
octal = (decimal % 8) + octal;
decimal = Math.floor(decimal / 8);
}
return octal;
}
/**
* 十进制转十六进制
* @param decimal
* @returns
*/
private decimalToHexadecimal(decimal: number): string {
let hexadecimal = "";
const hexDigits = "0123456789ABCDEF";
// 通过取余运算进行转换
while (decimal > 0) {
hexadecimal = hexDigits[decimal % 16 ] + hexadecimal;
decimal = Math.floor(decimal / 16);
}
return hexadecimal;
}
/**
* 十六进制转十进制
* @param hexadecimal
* @returns
*/
private hexadecimalToDecimal(hexadecimal: string): number {
let decimal = 0;
for (let i = 0; i < hexadecimal.length; i++) {
const digit = hexadecimal[i];
const value = parseInt(digit, 16);
decimal += value * Math.pow(16, hexadecimal.length - i - 1);
}
return decimal;
}