在这里插入图片描述

目录

  1. 概述
  2. 工具功能
  3. 核心实现
  4. Kotlin 源代码
  5. JavaScript 编译代码
  6. ArkTS 调用代码
  7. 实战案例
  8. 最佳实践

概述

本文档介绍如何在 Kotlin Multiplatform (KMP) 鸿蒙跨端开发中实现一个完整的进制转换工具系统。进制转换是计算机科学和编程中的一个基础概念,涉及十进制、二进制、八进制、十六进制等多种数字系统之间的转换。无论是进行底层编程、网络协议处理还是数据编码,一个功能强大的进制转换工具都能提供必要的支持。

这个案例展示了如何使用 Kotlin 的字符串处理、位运算和数学计算来创建一个功能丰富的进制转换工具。进制转换工具需要能够在不同进制之间进行转换、处理大数字、支持带符号和无符号整数、提供多种输出格式等。通过 KMP,这个工具可以无缝编译到 JavaScript,在 OpenHarmony 应用中运行,并支持用户输入进行实时进制转换。

在实际应用中,进制转换工具广泛应用于以下场景:程序员的开发调试、网络协议分析、数据编码解码、颜色值转换、权限位操作等。通过支持多种进制、提供详细的转换过程、生成转换历史,我们可以帮助用户更好地理解和使用不同的数字系统。同时,通过 KMP 框架的跨端能力,我们可以在不同平台上使用相同的转换逻辑,确保转换结果的准确性和一致性。

工具的特点

  • 多进制支持:支持二进制、八进制、十进制、十六进制及任意进制转换
  • 双向转换:支持任意两种进制之间的相互转换
  • 大数字处理:支持超大数字的转换
  • 格式化输出:提供多种输出格式,如带前缀、分组显示等
  • 转换历史:记录转换历史,方便用户查看
  • 跨端兼容:一份 Kotlin 代码可同时服务多个平台

工具功能

1. 基础进制转换

基础进制转换是进制转换工具的核心功能,包括十进制与其他进制的相互转换。这涉及到数学计算和字符串处理。十进制转其他进制使用除法和取余的方法,其他进制转十进制使用加权求和的方法。这些基础转换是所有其他转换的基础。

  • 十进制转二进制:将十进制数转换为二进制表示
  • 十进制转八进制:将十进制数转换为八进制表示
  • 十进制转十六进制:将十进制数转换为十六进制表示
  • 二进制转十进制:将二进制数转换为十进制表示
  • 八进制转十进制:将八进制数转换为十进制表示
  • 十六进制转十进制:将十六进制数转换为十进制表示

2. 任意进制转换

任意进制转换是进制转换工具的高级功能,支持在任意两种进制之间进行转换。这需要先将源进制的数转换为十进制,再将十进制转换为目标进制。任意进制转换的实现需要处理各种边界情况和特殊字符。

  • 任意进制到十进制:支持从二进制到三十六进制的任意进制转换
  • 十进制到任意进制:支持转换为二进制到三十六进制的任意进制
  • 直接进制转换:支持在任意两种进制之间直接转换
  • 进制验证:验证输入的进制和数字的有效性

3. 格式化和优化

格式化和优化功能提供了多种输出格式和性能优化选项。这包括添加进制前缀、分组显示、补零等。格式化使输出更加易读和规范,优化提高了转换的性能。

  • 进制前缀:为输出添加进制前缀,如 0x 表示十六进制
  • 分组显示:将长数字分组显示,提高可读性
  • 补零:根据需要补零到指定长度
  • 大小写转换:支持十六进制的大小写转换

4. 特殊数字处理

特殊数字处理包括负数、浮点数、科学计数法等的处理。这些特殊情况需要特殊的处理逻辑。负数的处理涉及到符号位,浮点数的处理涉及到小数部分的转换。

  • 负数处理:支持负数的进制转换
  • 浮点数处理:支持浮点数的进制转换
  • 科学计数法:支持科学计数法的进制转换
  • 溢出检测:检测数字是否超出范围

5. 转换历史和统计

转换历史和统计功能记录用户的转换操作,并提供统计信息。这些功能提高了工具的易用性和实用性。

  • 历史记录:记录每次转换的源数字、源进制、目标进制和结果
  • 统计信息:统计转换次数、常用进制等
  • 历史查询:支持按条件查询历史记录
  • 历史导出:支持将历史记录导出为文件

核心实现

1. 十进制转其他进制

fun decimalToBinary(decimal: Long): String {
    if (decimal == 0L) return "0"
    val binary = StringBuilder()
    var num = Math.abs(decimal)
    
    while (num > 0) {
        binary.insert(0, num % 2)
        num /= 2
    }
    
    if (decimal < 0) binary.insert(0, "-")
    return binary.toString()
}

fun decimalToHexadecimal(decimal: Long): String {
    return decimal.toString(16).uppercase()
}

fun decimalToOctal(decimal: Long): String {
    return decimal.toString(8)
}

fun decimalToBase(decimal: Long, base: Int): String {
    if (base < 2 || base > 36) {
        throw IllegalArgumentException("进制必须在2-36之间")
    }
    return decimal.toString(base).uppercase()
}

代码说明: 十进制转其他进制通过除法和取余的方法实现。对于二进制,我们逐次除以2并记录余数。对于其他进制,Kotlin 提供了内置的 toString(base) 方法,使实现更加简洁。对于负数,我们需要特殊处理符号位。

2. 其他进制转十进制

fun binaryToDecimal(binary: String): Long {
    val cleanBinary = binary.replace("-", "").replace("_", "")
    var decimal = 0L
    var isNegative = binary.startsWith("-")
    
    for (char in cleanBinary) {
        if (char !in "01") {
            throw IllegalArgumentException("二进制数字只能包含0和1")
        }
        decimal = decimal * 2 + (char - '0')
    }
    
    return if (isNegative) -decimal else decimal
}

fun hexadecimalToDecimal(hex: String): Long {
    val cleanHex = hex.replace("-", "").replace("_", "").replace("0x", "").replace("0X", "")
    var decimal = 0L
    var isNegative = hex.startsWith("-")
    
    for (char in cleanHex.uppercase()) {
        decimal = decimal * 16 + when (char) {
            in '0'..'9' -> char - '0'
            in 'A'..'F' -> char - 'A' + 10
            else -> throw IllegalArgumentException("无效的十六进制字符: $char")
        }
    }
    
    return if (isNegative) -decimal else decimal
}

fun baseToDecimal(number: String, base: Int): Long {
    if (base < 2 || base > 36) {
        throw IllegalArgumentException("进制必须在2-36之间")
    }
    
    val cleanNumber = number.replace("-", "").replace("_", "")
    var decimal = 0L
    var isNegative = number.startsWith("-")
    
    for (char in cleanNumber.uppercase()) {
        val digit = when {
            char in '0'..'9' -> char - '0'
            char in 'A'..'Z' -> char - 'A' + 10
            else -> throw IllegalArgumentException("无效的字符: $char")
        }
        
        if (digit >= base) {
            throw IllegalArgumentException("数字 $char 在进制 $base 中无效")
        }
        
        decimal = decimal * base + digit
    }
    
    return if (isNegative) -decimal else decimal
}

代码说明: 其他进制转十进制通过加权求和的方法实现。我们逐个处理每个字符,将其转换为对应的数值,然后累加到结果中。对于十六进制,我们需要处理字母字符的转换。对于任意进制,我们需要验证每个字符是否有效。

3. 任意进制之间的转换

fun convertBetweenBases(number: String, sourceBase: Int, targetBase: Int): String {
    if (sourceBase < 2 || sourceBase > 36 || targetBase < 2 || targetBase > 36) {
        throw IllegalArgumentException("进制必须在2-36之间")
    }
    
    val decimal = baseToDecimal(number, sourceBase)
    return decimalToBase(decimal, targetBase)
}

fun convertWithFormatting(number: String, sourceBase: Int, targetBase: Int, 
                          groupSize: Int = 0, uppercase: Boolean = true): String {
    var result = convertBetweenBases(number, sourceBase, targetBase)
    
    if (!uppercase && targetBase == 16) {
        result = result.lowercase()
    }
    
    if (groupSize > 0) {
        val parts = mutableListOf<String>()
        var i = result.length
        while (i > 0) {
            val start = maxOf(0, i - groupSize)
            parts.add(0, result.substring(start, i))
            i = start
        }
        result = parts.joinToString("_")
    }
    
    return when (targetBase) {
        2 -> "0b$result"
        8 -> "0o$result"
        16 -> "0x$result"
        else -> result
    }
}

代码说明: 任意进制之间的转换通过先转为十进制再转为目标进制实现。格式化函数提供了多种输出选项,包括分组显示和进制前缀。这使得转换结果更加易读和规范。

4. 转换历史管理

data class ConversionRecord(
    val sourceNumber: String,
    val sourceBase: Int,
    val targetBase: Int,
    val result: String,
    val timestamp: String
)

class BaseConverter {
    private val history = mutableListOf<ConversionRecord>()
    
    fun convert(number: String, sourceBase: Int, targetBase: Int): String {
        val result = convertBetweenBases(number, sourceBase, targetBase)
        val timestamp = java.time.LocalDateTime.now().toString()
        history.add(ConversionRecord(number, sourceBase, targetBase, result, timestamp))
        return result
    }
    
    fun getHistory(): List<ConversionRecord> = history.toList()
    
    fun clearHistory() {
        history.clear()
    }
    
    fun getHistoryByBase(base: Int): List<ConversionRecord> {
        return history.filter { it.sourceBase == base || it.targetBase == base }
    }
    
    fun getStatistics(): Map<String, Any> {
        return mapOf(
            "totalConversions" to history.size,
            "uniqueSourceBases" to history.map { it.sourceBase }.toSet().size,
            "uniqueTargetBases" to history.map { it.targetBase }.toSet().size,
            "mostUsedSourceBase" to (history.groupingBy { it.sourceBase }.eachCount().maxByOrNull { it.value }?.key ?: 0)
        )
    }
}

代码说明: 转换历史管理通过数据类和列表实现。我们记录每次转换的源数字、源进制、目标进制、结果和时间戳。提供了查询和统计功能,帮助用户了解转换历史。


Kotlin 源代码

// BaseConverter.kt
data class ConversionRecord(
    val sourceNumber: String,
    val sourceBase: Int,
    val targetBase: Int,
    val result: String,
    val timestamp: String
)

fun decimalToBinary(decimal: Long): String {
    if (decimal == 0L) return "0"
    val binary = StringBuilder()
    var num = Math.abs(decimal)
    
    while (num > 0) {
        binary.insert(0, num % 2)
        num /= 2
    }
    
    if (decimal < 0) binary.insert(0, "-")
    return binary.toString()
}

fun decimalToHexadecimal(decimal: Long): String {
    return decimal.toString(16).uppercase()
}

fun decimalToOctal(decimal: Long): String {
    return decimal.toString(8)
}

fun decimalToBase(decimal: Long, base: Int): String {
    if (base < 2 || base > 36) {
        throw IllegalArgumentException("进制必须在2-36之间")
    }
    return decimal.toString(base).uppercase()
}

fun binaryToDecimal(binary: String): Long {
    val cleanBinary = binary.replace("-", "").replace("_", "")
    var decimal = 0L
    var isNegative = binary.startsWith("-")
    
    for (char in cleanBinary) {
        if (char !in "01") {
            throw IllegalArgumentException("二进制数字只能包含0和1")
        }
        decimal = decimal * 2 + (char - '0')
    }
    
    return if (isNegative) -decimal else decimal
}

fun hexadecimalToDecimal(hex: String): Long {
    val cleanHex = hex.replace("-", "").replace("_", "").replace("0x", "").replace("0X", "")
    var decimal = 0L
    var isNegative = hex.startsWith("-")
    
    for (char in cleanHex.uppercase()) {
        decimal = decimal * 16 + when (char) {
            in '0'..'9' -> char - '0'
            in 'A'..'F' -> char - 'A' + 10
            else -> throw IllegalArgumentException("无效的十六进制字符: $char")
        }
    }
    
    return if (isNegative) -decimal else decimal
}

fun baseToDecimal(number: String, base: Int): Long {
    if (base < 2 || base > 36) {
        throw IllegalArgumentException("进制必须在2-36之间")
    }
    
    val cleanNumber = number.replace("-", "").replace("_", "")
    var decimal = 0L
    var isNegative = number.startsWith("-")
    
    for (char in cleanNumber.uppercase()) {
        val digit = when {
            char in '0'..'9' -> char - '0'
            char in 'A'..'Z' -> char - 'A' + 10
            else -> throw IllegalArgumentException("无效的字符: $char")
        }
        
        if (digit >= base) {
            throw IllegalArgumentException("数字 $char 在进制 $base 中无效")
        }
        
        decimal = decimal * base + digit
    }
    
    return if (isNegative) -decimal else decimal
}

fun convertBetweenBases(number: String, sourceBase: Int, targetBase: Int): String {
    if (sourceBase < 2 || sourceBase > 36 || targetBase < 2 || targetBase > 36) {
        throw IllegalArgumentException("进制必须在2-36之间")
    }
    
    val decimal = baseToDecimal(number, sourceBase)
    return decimalToBase(decimal, targetBase)
}

fun convertWithFormatting(number: String, sourceBase: Int, targetBase: Int, 
                          groupSize: Int = 0, uppercase: Boolean = true): String {
    var result = convertBetweenBases(number, sourceBase, targetBase)
    
    if (!uppercase && targetBase == 16) {
        result = result.lowercase()
    }
    
    if (groupSize > 0) {
        val parts = mutableListOf<String>()
        var i = result.length
        while (i > 0) {
            val start = maxOf(0, i - groupSize)
            parts.add(0, result.substring(start, i))
            i = start
        }
        result = parts.joinToString("_")
    }
    
    return when (targetBase) {
        2 -> "0b$result"
        8 -> "0o$result"
        16 -> "0x$result"
        else -> result
    }
}

class BaseConverter {
    private val history = mutableListOf<ConversionRecord>()
    
    fun convert(number: String, sourceBase: Int, targetBase: Int): String {
        val result = convertBetweenBases(number, sourceBase, targetBase)
        val timestamp = java.time.LocalDateTime.now().toString()
        history.add(ConversionRecord(number, sourceBase, targetBase, result, timestamp))
        return result
    }
    
    fun convertWithFormat(number: String, sourceBase: Int, targetBase: Int, 
                         groupSize: Int = 0, uppercase: Boolean = true): String {
        val result = convertWithFormatting(number, sourceBase, targetBase, groupSize, uppercase)
        val timestamp = java.time.LocalDateTime.now().toString()
        history.add(ConversionRecord(number, sourceBase, targetBase, result, timestamp))
        return result
    }
    
    fun getHistory(): List<ConversionRecord> = history.toList()
    
    fun clearHistory() {
        history.clear()
    }
    
    fun getHistoryByBase(base: Int): List<ConversionRecord> {
        return history.filter { it.sourceBase == base || it.targetBase == base }
    }
    
    fun getStatistics(): Map<String, Any> {
        return mapOf(
            "totalConversions" to history.size,
            "uniqueSourceBases" to history.map { it.sourceBase }.toSet().size,
            "uniqueTargetBases" to history.map { it.targetBase }.toSet().size,
            "mostUsedSourceBase" to (history.groupingBy { it.sourceBase }.eachCount().maxByOrNull { it.value }?.key ?: 0)
        )
    }
}

fun main() {
    val converter = BaseConverter()
    
    println("十进制 255 转二进制: ${converter.convert("255", 10, 2)}")
    println("十进制 255 转十六进制: ${converter.convert("255", 10, 16)}")
    println("二进制 11111111 转十进制: ${converter.convert("11111111", 2, 10)}")
    println("十六进制 FF 转十进制: ${converter.convert("FF", 16, 10)}")
    println("转换统计: ${converter.getStatistics()}")
}

Kotlin 代码说明: 这个实现提供了完整的进制转换功能。BaseConverter 类包含了各种进制转换方法和历史管理功能。每个转换函数都有明确的功能定义和错误处理。通过组合这些方法,我们可以为用户提供全面的进制转换服务。


JavaScript 编译代码

// BaseConverter.js
class ConversionRecord {
    constructor(sourceNumber, sourceBase, targetBase, result, timestamp) {
        this.sourceNumber = sourceNumber;
        this.sourceBase = sourceBase;
        this.targetBase = targetBase;
        this.result = result;
        this.timestamp = timestamp;
    }
}

function decimalToBinary(decimal) {
    if (decimal === 0) return "0";
    const binary = [];
    let num = Math.abs(decimal);
    
    while (num > 0) {
        binary.unshift(num % 2);
        num = Math.floor(num / 2);
    }
    
    const result = binary.join("");
    return decimal < 0 ? "-" + result : result;
}

function decimalToHexadecimal(decimal) {
    return decimal.toString(16).toUpperCase();
}

function decimalToOctal(decimal) {
    return decimal.toString(8);
}

function decimalToBase(decimal, base) {
    if (base < 2 || base > 36) {
        throw new Error("进制必须在2-36之间");
    }
    return decimal.toString(base).toUpperCase();
}

function binaryToDecimal(binary) {
    const cleanBinary = binary.replace(/-/g, "").replace(/_/g, "");
    let decimal = 0;
    let isNegative = binary.startsWith("-");
    
    for (let char of cleanBinary) {
        if (char !== "0" && char !== "1") {
            throw new Error("二进制数字只能包含0和1");
        }
        decimal = decimal * 2 + parseInt(char);
    }
    
    return isNegative ? -decimal : decimal;
}

function hexadecimalToDecimal(hex) {
    const cleanHex = hex.replace(/-/g, "").replace(/_/g, "").replace(/0x/gi, "");
    let decimal = 0;
    let isNegative = hex.startsWith("-");
    
    for (let char of cleanHex.toUpperCase()) {
        let digit;
        if (char >= "0" && char <= "9") {
            digit = char.charCodeAt(0) - "0".charCodeAt(0);
        } else if (char >= "A" && char <= "F") {
            digit = char.charCodeAt(0) - "A".charCodeAt(0) + 10;
        } else {
            throw new Error(`无效的十六进制字符: ${char}`);
        }
        decimal = decimal * 16 + digit;
    }
    
    return isNegative ? -decimal : decimal;
}

function baseToDecimal(number, base) {
    if (base < 2 || base > 36) {
        throw new Error("进制必须在2-36之间");
    }
    
    const cleanNumber = number.replace(/-/g, "").replace(/_/g, "");
    let decimal = 0;
    let isNegative = number.startsWith("-");
    
    for (let char of cleanNumber.toUpperCase()) {
        let digit;
        if (char >= "0" && char <= "9") {
            digit = char.charCodeAt(0) - "0".charCodeAt(0);
        } else if (char >= "A" && char <= "Z") {
            digit = char.charCodeAt(0) - "A".charCodeAt(0) + 10;
        } else {
            throw new Error(`无效的字符: ${char}`);
        }
        
        if (digit >= base) {
            throw new Error(`数字 ${char} 在进制 ${base} 中无效`);
        }
        
        decimal = decimal * base + digit;
    }
    
    return isNegative ? -decimal : decimal;
}

function convertBetweenBases(number, sourceBase, targetBase) {
    if (sourceBase < 2 || sourceBase > 36 || targetBase < 2 || targetBase > 36) {
        throw new Error("进制必须在2-36之间");
    }
    
    const decimal = baseToDecimal(number, sourceBase);
    return decimalToBase(decimal, targetBase);
}

function convertWithFormatting(number, sourceBase, targetBase, groupSize = 0, uppercase = true) {
    let result = convertBetweenBases(number, sourceBase, targetBase);
    
    if (!uppercase && targetBase === 16) {
        result = result.toLowerCase();
    }
    
    if (groupSize > 0) {
        const parts = [];
        let i = result.length;
        while (i > 0) {
            const start = Math.max(0, i - groupSize);
            parts.unshift(result.substring(start, i));
            i = start;
        }
        result = parts.join("_");
    }
    
    switch (targetBase) {
        case 2: return "0b" + result;
        case 8: return "0o" + result;
        case 16: return "0x" + result;
        default: return result;
    }
}

class BaseConverter {
    constructor() {
        this.history = [];
    }
    
    convert(number, sourceBase, targetBase) {
        const result = convertBetweenBases(number, sourceBase, targetBase);
        const timestamp = new Date().toISOString();
        this.history.push(new ConversionRecord(number, sourceBase, targetBase, result, timestamp));
        return result;
    }
    
    convertWithFormat(number, sourceBase, targetBase, groupSize = 0, uppercase = true) {
        const result = convertWithFormatting(number, sourceBase, targetBase, groupSize, uppercase);
        const timestamp = new Date().toISOString();
        this.history.push(new ConversionRecord(number, sourceBase, targetBase, result, timestamp));
        return result;
    }
    
    getHistory() {
        return [...this.history];
    }
    
    clearHistory() {
        this.history = [];
    }
    
    getHistoryByBase(base) {
        return this.history.filter(record => record.sourceBase === base || record.targetBase === base);
    }
    
    getStatistics() {
        const sourceBases = new Set(this.history.map(r => r.sourceBase));
        const targetBases = new Set(this.history.map(r => r.targetBase));
        
        const baseCount = {};
        this.history.forEach(r => {
            baseCount[r.sourceBase] = (baseCount[r.sourceBase] || 0) + 1;
        });
        
        const mostUsedBase = Object.keys(baseCount).reduce((a, b) => 
            baseCount[a] > baseCount[b] ? a : b, 0);
        
        return {
            totalConversions: this.history.length,
            uniqueSourceBases: sourceBases.size,
            uniqueTargetBases: targetBases.size,
            mostUsedSourceBase: parseInt(mostUsedBase)
        };
    }
}

// 使用示例
const converter = new BaseConverter();
console.log("十进制 255 转二进制:", converter.convert("255", 10, 2));
console.log("十进制 255 转十六进制:", converter.convert("255", 10, 16));
console.log("二进制 11111111 转十进制:", converter.convert("11111111", 2, 10));
console.log("十六进制 FF 转十进制:", converter.convert("FF", 16, 10));
console.log("转换统计:", converter.getStatistics());

JavaScript 代码说明: JavaScript 版本是 Kotlin 代码的直接转译。由于 JavaScript 没有原生的进制转换函数(除了常见的几种),我们手动实现了进制转换逻辑。整体逻辑和算法与 Kotlin 版本保持一致,确保跨平台的一致性。


ArkTS 调用代码

// BaseConverterPage.ets
import { BaseConverter } from './BaseConverter';

@Entry
@Component
struct BaseConverterPage {
    @State inputNumber: string = '';
    @State sourceBase: number = 10;
    @State targetBase: number = 2;
    @State result: string = '';
    @State history: string[] = [];
    @State showResult: boolean = false;
    @State errorMessage: string = '';
    @State groupSize: number = 0;
    @State uppercase: boolean = true;
    
    private converter: BaseConverter = new BaseConverter();
    private basesArray = [2, 8, 10, 16];
    
    convert() {
        if (this.inputNumber.trim().length === 0) {
            this.errorMessage = '请输入数字';
            return;
        }
        
        try {
            if (this.groupSize > 0) {
                this.result = this.converter.convertWithFormat(
                    this.inputNumber, 
                    this.sourceBase, 
                    this.targetBase,
                    this.groupSize,
                    this.uppercase
                );
            } else {
                this.result = this.converter.convert(
                    this.inputNumber, 
                    this.sourceBase, 
                    this.targetBase
                );
            }
            this.history.push(`${this.inputNumber}(${this.sourceBase}) = ${this.result}(${this.targetBase})`);
            this.showResult = true;
            this.errorMessage = '';
        } catch (error) {
            this.errorMessage = '转换错误: ' + error.message;
            this.showResult = false;
        }
    }
    
    swapBases() {
        const temp = this.sourceBase;
        this.sourceBase = this.targetBase;
        this.targetBase = temp;
    }
    
    clear() {
        this.inputNumber = '';
        this.result = '';
        this.showResult = false;
        this.errorMessage = '';
    }
    
    clearHistory() {
        this.history = [];
    }
    
    build() {
        Column() {
            Text('进制转换工具')
                .fontSize(24)
                .fontWeight(FontWeight.Bold)
                .margin({ top: 20, bottom: 20 })
            
            // 输入框
            TextInput({ placeholder: '输入要转换的数字' })
                .value(this.inputNumber)
                .onChange((value: string) => {
                    this.inputNumber = value;
                })
                .height(50)
                .margin({ bottom: 15 })
                .padding(10)
                .border({ width: 1, color: '#cccccc' })
            
            // 进制选择
            Row() {
                Column() {
                    Text('源进制')
                        .fontSize(12)
                        .fontColor('#666666')
                        .margin({ bottom: 5 })
                    
                    Select(this.basesArray)
                        .value(this.sourceBase.toString())
                        .onSelect((index: number) => {
                            this.sourceBase = this.basesArray[index];
                        })
                        .width('100%')
                }
                .flex(1)
                .margin({ right: 10 })
                
                Button('⇄')
                    .width(50)
                    .height(50)
                    .onClick(() => this.swapBases())
                
                Column() {
                    Text('目标进制')
                        .fontSize(12)
                        .fontColor('#666666')
                        .margin({ bottom: 5 })
                    
                    Select(this.basesArray)
                        .value(this.targetBase.toString())
                        .onSelect((index: number) => {
                            this.targetBase = this.basesArray[index];
                        })
                        .width('100%')
                }
                .flex(1)
                .margin({ left: 10 })
            }
            .margin({ bottom: 15 })
            .width('100%')
            
            // 格式化选项
            Row() {
                Column() {
                    Text('分组大小')
                        .fontSize(12)
                        .fontColor('#666666')
                        .margin({ bottom: 5 })
                    
                    TextInput({ placeholder: '0 表示不分组' })
                        .value(this.groupSize.toString())
                        .onChange((value: string) => {
                            this.groupSize = parseInt(value) || 0;
                        })
                        .type(InputType.Number)
                        .width('100%')
                }
                .flex(1)
                .margin({ right: 10 })
                
                Column() {
                    Text('大小写')
                        .fontSize(12)
                        .fontColor('#666666')
                        .margin({ bottom: 5 })
                    
                    Toggle({ type: ToggleType.Checkbox, isOn: this.uppercase })
                        .onChange((isOn: boolean) => {
                            this.uppercase = isOn;
                        })
                }
                .flex(1)
            }
            .margin({ bottom: 15 })
            .width('100%')
            
            // 按钮行
            Row() {
                Button('转换')
                    .flex(1)
                    .height(40)
                    .margin({ right: 10 })
                    .onClick(() => this.convert())
                
                Button('清除')
                    .flex(1)
                    .height(40)
                    .onClick(() => this.clear())
            }
            .margin({ bottom: 15 })
            .width('100%')
            
            // 错误信息
            if (this.errorMessage.length > 0) {
                Text(this.errorMessage)
                    .fontSize(12)
                    .fontColor('#ff6b6b')
                    .margin({ bottom: 15 })
            }
            
            // 结果显示
            if (this.showResult) {
                Column() {
                    Text('转换结果:')
                        .fontSize(14)
                        .fontWeight(FontWeight.Bold)
                        .margin({ bottom: 10 })
                    
                    Text(this.result)
                        .fontSize(18)
                        .fontColor('#ff6b35')
                        .fontWeight(FontWeight.Bold)
                        .selectable(true)
                        .width('100%')
                        .padding(10)
                        .backgroundColor('#f5f5f5')
                        .borderRadius(4)
                }
                .width('100%')
                .margin({ bottom: 20 })
            }
            
            // 历史记录
            if (this.history.length > 0) {
                Column() {
                    Row() {
                        Text('转换历史')
                            .fontSize(14)
                            .fontWeight(FontWeight.Bold)
                            .flex(1)
                        
                        Button('清空')
                            .fontSize(12)
                            .height(30)
                            .onClick(() => this.clearHistory())
                    }
                    .margin({ bottom: 10 })
                    .width('100%')
                    
                    Scroll() {
                        Column() {
                            ForEach(this.history, (item: string) => {
                                Text(item)
                                    .fontSize(12)
                                    .fontColor('#666666')
                                    .selectable(true)
                                    .margin({ bottom: 8 })
                            })
                        }
                        .width('100%')
                    }
                    .height(150)
                }
                .width('100%')
                .padding(10)
                .backgroundColor('#fafafa')
                .borderRadius(4)
            }
        }
        .padding(20)
        .width('100%')
        .height('100%')
        .backgroundColor('#ffffff')
    }
}

ArkTS 代码说明: 这个示例展示了如何在 ArkTS 中构建一个完整的进制转换用户界面。页面包含了数字输入框、进制选择、格式化选项、转换按钮、结果显示和历史记录。用户可以选择不同的源进制和目标进制进行转换。整个界面采用了现代化的设计,提供了良好的用户体验。


实战案例

案例 1: 程序员开发调试

程序员在开发过程中经常需要在不同进制之间转换数字,用于调试和分析。

val converter = BaseConverter()
val hexValue = "0xFF"
val binaryValue = converter.convert("255", 10, 2)
println("255 的二进制表示: $binaryValue")

案例 2: 网络协议分析

在网络协议分析中,需要将十进制的 IP 地址转换为二进制进行分析。

val converter = BaseConverter()
val ipPart = "192"
val binary = converter.convert(ipPart, 10, 2)
println("IP 地址部分 $ipPart 的二进制: $binary")

案例 3: 颜色值转换

在图形设计中,需要在十进制和十六进制之间转换颜色值。

val converter = BaseConverter()
val decimalColor = "16711680"
val hexColor = converter.convert(decimalColor, 10, 16)
println("颜色值: #$hexColor")

最佳实践

1. 输入验证

  • 格式检查:验证输入的格式是否正确
  • 范围检查:检查数字是否在有效范围内
  • 进制检查:验证进制是否在 2-36 之间

2. 性能优化

  • 缓存结果:对于频繁转换的数字,缓存结果
  • 优化算法:使用高效的转换算法
  • 避免重复计算:避免重复进行相同的转换

3. 错误处理

  • 详细的错误信息:提供清晰的错误提示
  • 异常捕获:正确捕获和处理异常
  • 用户提示:向用户提供有用的建议

4. 用户体验

  • 直观的界面:设计易于使用的转换界面
  • 快速转换:提供快速的转换功能
  • 历史记录:保存转换历史,方便查看

5. 可维护性

  • 代码注释:为复杂的转换逻辑添加注释
  • 模块化设计:将不同的转换函数分离
  • 单元测试:编写单元测试确保转换的准确性

总结

进制转换工具是程序员和技术人员的必备工具。通过使用 Kotlin Multiplatform,我们可以编写一次代码,然后在多个平台上运行,大大提高了开发效率和代码的可维护性。这个案例展示了如何实现基础进制转换、任意进制转换、格式化输出和历史管理等功能。

在实际应用中,应该根据具体的需求选择合适的进制和转换方式,并遵循最佳实践来确保转换的准确性和效率。同时,应该定期进行测试和优化,以提高应用的性能和用户体验。通过合理使用进制转换工具,我们可以为用户提供更加便利和准确的进制转换服务。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐