当前位置: 首页 > news >正文

OpenHarmony鸿蒙PC完成ohos-sdk适配自动签名编译rust_decimal三方库,用于高精度十进制浮点场景

欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
AtomGit 仓库地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_rust_cargo

本文讲解鸿蒙 PC 端 Rust 开发环境搭建,鸿蒙基于 musl 库、强制二进制签名,无法直接使用通用 Linux 编译产物。需借助鸿蒙专属包管理器 Harmonybrew,提供两套编译方案:方案一安装 llvm-gcc-compat,零配置开箱即用;方案二仅安装 ohos-sdk,需手动配置 Cargo 链接器,二者都依托 ohos-sdk 完成自动签名编译。

完整的过程可以参考一下:

【OpenHarmony 鸿蒙 PC + CodeArts IDE 实现 Rust开发完整开发环境搭建指南】


一、rust_decimal 库介绍

作用

rust_decimal是 Rust 高精度十进制浮点库,专门解决f32/f64二进制浮点数精度丢失问题(金钱、财务、计费、汇率、库存金额场景绝对不能用 f64)。

核心能力

  1. 高精度十进制运算,最多支持 28 位有效数字,金融标准精度;
  2. 支持加减乘除、四舍五入、向上/向下取整、保留指定位小数;
  3. 自带货币格式化、字符串互转、整数互相转换;
  4. 提供四则运算、比较、取模、幂运算;
  5. 支持 serde 序列化,可直接存 JSON、数据库金额字段。

适用场景

支付金额、订单总价、商品单价、税费计算、汇率换算、财务报表、记账系统、积分金额。

二进制浮点数坑对比

// f64 致命缺陷:0.1 + 0.2 != 0.3println!("{}",0.1+0.2);// 输出 0.30000000000000004// rust_decimal 无精度丢失,0.1 + 0.2 严格等于 0.3

二、安装

cargoaddrust_decimal--featuresstdcargoaddrust_decimal_macros

Cargo.toml

[package] name = "decimal_demo" version = "0.1.0" edition = "2021" [dependencies] rust_decimal = { version = "1.36", features = ["std"] } rust_decimal_macros = "1.36"
  • rust_decimal_macros:提供dec!宏,快速字面量定义十进制数字

三、完整零报错示例代码 main.rs

userust_decimal::prelude::*;userust_decimal_macros::dec;fnmain(){println!("===== 1. 基础创建 Decimal 对象(宏/字符串/整数) =====");demo_create_decimal();println!("\n===== 2. 四则运算(无精度丢失) =====");demo_calc();println!("\n===== 3. 小数舍入、保留2位小数(金额场景) =====");demo_round();println!("\n===== 4. 简单金额格式化输出(人民币) =====");demo_format_money();println!("\n===== 5. 比较大小、取绝对值、取反 =====");demo_compare_math();println!("\n===== 6. 字符串、数字互相转换 =====");demo_convert();}/// 1. 三种创建Decimal方式fndemo_create_decimal(){// 宏直接写小数,最常用letprice=dec!(99.99);// 从整数构造letnum=Decimal::from(1000);// 从安全字符串构造(前端传金额字符串推荐)letfrom_str=Decimal::from_str("0.12345").unwrap();println!("商品单价: {}",price);println!("整数转换: {}",num);println!("字符串构造: {}",from_str);// 经典浮点坑对比leta=dec!(0.1);letb=dec!(0.2);println!("0.1 + 0.2 = {}",a+b);// 精确等于0.3,无误差}/// 2. 加减乘除四则运算fndemo_calc(){letunit_price=dec!(29.99);letcount=dec!(3);lettax_rate=dec!(0.09);letsubtotal=unit_price*count;// 小计lettax=subtotal*tax_rate;// 税费lettotal=subtotal+tax;// 总价println!("单价{} × 数量{} = 小计{}",unit_price,count,subtotal);println!("9%税费: {}",tax);println!("订单总金额: {}",total);// 除法lettotal_money=dec!(99.9);letpeople=dec!(3);letavg=total_money/people;println!("三人平分99.9,人均: {}",avg);}/// 3. 金额四舍五入、保留2位小数(修复RoundingStrategy不存在Ceiling/Floor)fndemo_round(){letraw=dec!(123.4567);// 默认四舍五入保留2位小数(金融通用)letround_2=raw.round_dp(2);// 向上取整(替代Ceiling)letceil_2=raw.ceil();// 向下取整(替代Floor)letfloor_2=raw.floor();println!("原始值: {}",raw);println!("四舍五入保留2位: {}",round_2);println!("整体向上取整: {}",ceil_2);println!("整体向下取整: {}",floor_2);}/// 4. 简单货币格式化(移除FormatOptions不存在API)fndemo_format_money(){letmoney=dec!(1288.56);println!("格式化金额: ¥{}",money.round_dp(2));letsmall=dec!(0.05);println!("小额金额: ¥{}",small.round_dp(2));}/// 5. 比较、绝对值、取反fndemo_compare_math(){leta=dec!(10.5);letb=dec!(8.2);letneg=dec!(-20.33);println!("10.5 > 8.2 ? {}",a>b);println!("相等判断: {}",dec!(5.0)==dec!(5));println!("负数绝对值: {}",neg.abs());println!("数字取反: {}",-a);}/// 6. 类型互相转换fndemo_convert(){letval=dec!(1234.56);// Decimal → 字符串lets=val.to_string();println!("转字符串: {}",s);// Decimal → i64(截断小数)letint_part=val.trunc().to_i64().unwrap();println!("取整数部分i64: {}",int_part);// 字符串转回Decimalletparse_back=Decimal::from_str(&s).unwrap();println!("字符串转回Decimal: {}",parse_back);}


一、库基础说明

rust_decimal是 Rust 金融高精度十进制库,专门解决 f32/f64 二进制浮点精度丢失问题0.1 + 0.2 ≠ 0.3),订单金额、支付、税费、记账场景必须使用,禁止用普通浮点数。
配套rust_decimal_macros提供dec!宏,快速创建十进制字面量。

头部导入

userust_decimal::prelude::*;userust_decimal_macros::dec;
  1. rust_decimal::prelude::*:预导入所有高频类型、方法、Trait(Decimal、运算、取整、转换方法),不用逐个单独导入。
  2. dec!宏:编译期生成高精度十进制数字,写法简洁,财务代码最常用。

main 入口函数

按业务常用场景分成6个模块依次执行:

  1. 创建Decimal数字的3种方式
  2. 加减乘除四则金融运算
  3. 小数保留、向上/向下取整
  4. 人民币金额打印格式化
  5. 大小比较、绝对值、负数取反
  6. Decimal 和字符串/整数互相转换

模块1 demo_create_decimal 创建数字

fndemo_create_decimal(){// 宏直接写小数,最常用letprice=dec!(99.99);// 从整数构造letnum=Decimal::from(1000);// 从安全字符串构造(前端传金额字符串推荐)letfrom_str=Decimal::from_str("0.12345").unwrap();println!("商品单价: {}",price);println!("整数转换: {}",num);println!("字符串构造: {}",from_str);// 经典浮点坑对比leta=dec!(0.1);letb=dec!(0.2);println!("0.1 + 0.2 = {}",a+b);// 精确等于0.3,无误差}

三种创建方式说明

  1. dec!(99.99)
    编译期直接解析数字生成Decimal,性能最高,写固定金额首选。
  2. Decimal::from(1000)
    i32/i64 整数转金额,适合库存数量、整数元数。
  3. Decimal::from_str("0.12345")
    前端接口、数据库取出的字符串金额专用。
    前端如果传数字0.1用JSON浮点传输会失真,统一传字符串再解析是行业规范。

浮点缺陷演示

f64二进制存储小数存在误差,0.1+0.2结果是0.30000000000000004
Decimal 使用十进制存储,计算完全精准,金融不会出现分钱差错。


模块2 demo_calc 四则运算(订单计算场景)

fndemo_calc(){letunit_price=dec!(29.99);letcount=dec!(3);lettax_rate=dec!(0.09);letsubtotal=unit_price*count;// 小计lettax=subtotal*tax_rate;// 税费lettotal=subtotal+tax;// 总价println!("单价{} × 数量{} = 小计{}",unit_price,count,subtotal);println!("9%税费: {}",tax);println!("订单总金额: {}",total);// 除法lettotal_money=dec!(99.9);letpeople=dec!(3);letavg=total_money/people;println!("三人平分99.9,人均: {}",avg);}

业务逻辑模拟

模拟电商订单计算:单价 × 数量 = 商品小计,小计 × 税率 = 税费,相加得到实付总价。
Decimal 重载+ - * /运算符,写法和普通数字完全一致,全程无精度丢失。
除法适合分摊金额、单价换算。


模块3 demo_round 小数保留与取整(金融核心)

fndemo_round(){letraw=dec!(123.4567);// 默认四舍五入保留2位小数(金融通用)letround_2=raw.round_dp(2);// 向上取整(替代Ceiling)letceil_2=raw.ceil();// 向下取整(替代Floor)letfloor_2=raw.floor();println!("原始值: {}",raw);println!("四舍五入保留2位: {}",round_2);println!("整体向上取整: {}",ceil_2);println!("整体向下取整: {}",floor_2);}

方法解释

  1. .round_dp(n)
    保留n位小数,默认四舍五入;人民币金额统一保留2位(元、分)。
  2. .ceil()向上取整
    不管小数多少直接进1,商家计费、运费计算常用。
  3. .floor()向下取整
    直接舍弃所有小数,退款、优惠抵扣场景使用。

模块4 demo_format_money 金额格式化打印

fndemo_format_money(){letmoney=dec!(1288.56);println!("格式化金额: ¥{}",money.round_dp(2));letsmall=dec!(0.05);println!("小额金额: ¥{}",small.round_dp(2));}

逻辑简单:输出人民币符号¥,同时统一保留两位小数,保证页面展示格式统一,不会出现1288.51288.567这种不合规金额。


模块5 demo_compare_math 比较与基础数学运算

fndemo_compare_math(){leta=dec!(10.5);letb=dec!(8.2);letneg=dec!(-20.33);println!("10.5 > 8.2 ? {}",a>b);println!("相等判断: {}",dec!(5.0)==dec!(5));println!("负数绝对值: {}",neg.abs());println!("数字取反: {}",-a);}
  1. 支持> < >= <= == !=全部比较运算符,用于判断满减门槛、余额是否充足;
  2. .abs()取绝对值,计算差价、手续费差额;
  3. -Decimal直接对数字取反,计算退款、负数余额。

模块6 demo_convert 类型互相转换

fndemo_convert(){letval=dec!(1234.56);// Decimal → 字符串lets=val.to_string();println!("转字符串: {}",s);// Decimal → i64(截断小数)letint_part=val.trunc().to_i64().unwrap();println!("取整数部分i64: {}",int_part);// 字符串转回Decimalletparse_back=Decimal::from_str(&s).unwrap();println!("字符串转回Decimal: {}",parse_back);}

转换业务用途

  1. .to_string():接口JSON返回金额、存入文本日志;
  2. .trunc().to_i64():舍弃小数只保留整数,用于把金额转为“分”存储到数据库整数字段;
  3. Decimal::from_str():后端接收前端字符串金额,反向解析。

全局开发规范总结

  1. 所有金额、汇率、计费数值禁止 f64/f32,统一 Decimal;
  2. 前后端传输金额优先字符串,规避浮点JSON失真;
  3. 展示、入库前一律用.round_dp(2)保留两位小数;
  4. 计算退款、运费时按需使用ceil()/floor()明确取整规则,避免财务纠纷。

四、代码分段详细解释

1. 导入

userust_decimal::prelude::*;userust_decimal_macros::dec;
  • prelude::*:一次性导入全部常用类型、Trait、枚举(Decimal、RoundingStrategy、FormatOptions等)
  • dec!宏:编译期直接生成高精度十进制字面量,财务代码首选

2. 创建Decimal三种方式

  1. dec!(123.45)宏:最简单,编译期求值,无运行时解析开销
  2. Decimal::from(i64/u64):整数转金额
  3. Decimal::from_str("0.123"):接收前端/数据库字符串金额,安全避免浮点误差

3. 四则运算核心优势

Decimal重载+ - * /运算符,运算全程十进制逻辑,不会出现二进制浮点微小误差,适合订单、税费、分润计算。

4. 舍入策略(金融必用)

  • .round_dp(n):默认四舍五入保留n位小数(人民币保留2位)
  • RoundingStrategy::Ceiling:向上进位(商家计费常用)
  • RoundingStrategy::Floor:向下舍弃(退款、扣减场景)

5. 货币格式化

FormatOptions配置千位分隔符、小数点分隔符,输出1,288.56标准金额展示格式。

6. 类型互转

  • 转字符串:接口返回、数据库存储
  • 转整数:提取元、分整数存储
  • 字符串反向解析:接收前端传入金额字符串

五、业务高频极简片段

1. 计算订单总价并保留2位小数

userust_decimal::prelude::*;userust_decimal_macros::dec;fncalc_total(price:Decimal,num:Decimal,tax:Decimal)->Decimal{lettotal=price*num*(dec!(1)+tax);total.round_dp(2)}

2. 安全解析前端金额字符串

fnparse_money(s:&str)->Option<Decimal>{Decimal::from_str(s).ok()}

3. 金额比较判断优惠门槛

letorder_total=dec!(299.9);iforder_total>=dec!(300){println!("满足满减条件");}

六、重要使用规范

  1. 所有金额禁止 f32/f64,一律使用 Decimal;
  2. 前后端传金额优先用字符串传输,避免JSON浮点失真;
  3. 存储数据库建议 decimal 字段,或存整数“分”;
  4. 展示金额前统一.round_dp(2)保留两位小数;
  5. 涉及计费扣费明确指定舍入策略,避免纠纷。
http://www.jsqmd.com/news/1039350/

相关文章:

  • TC815芯片蜂鸣器驱动电路设计:从原理到PCB布局实战
  • P6714 [CCO 2018] Wrong Answer 题解
  • 2026 珠海黄金回收去哪卖 滨海旧金上门到店变现实操攻略 - 靖昱黄金回收
  • Apache Solr Velocity模板注入漏洞(CVE-2019-17558)深度分析与实战复现
  • AccessGuard v0.8:RBAC + ABAC 融合 — TypeScript 交叉类型与类型收窄深度实战
  • 2026年更新:南通专业车库扫地机销售公司选择指南与深度剖析 - 品牌鉴赏官2026
  • 跨境电商翻译工具使用心得分享
  • 2026年新消息:石首车主如何甄选靠谱的全车隔音本地门店? - 品牌鉴赏官2026
  • 2026锦州防水补漏靠谱服务商盘点:屋面/厨卫/外墙/地下室渗水维修详解,适配辽西沿海大风盐雾防冻甄选指南 - 宅安选房屋修缮
  • 2026 年 6 月专业靠谱重大商事诉讼律师榜单,五位商事纠纷办案律师参考 - 外贸老黄
  • 房地产数字沙盘哪家好?
  • MPC801 TBSCR寄存器详解:从硬件定时器到精准时序控制实践
  • 2026临汾防水补漏靠谱服务商盘点:屋面/厨卫/外墙/地下室渗水维修详解,适配晋南黄土高原大风冻融甄选指南 - 宅安选房屋修缮
  • Redis篇(十三):Sentinel 故障转移、脑裂问题与 RedLock
  • 基于Hadoop的电商推荐系统有报告1(设计源文件+万字报告+讲解)(支持资料、图片参考_降重降ai)
  • 智能车竞赛中的挂名队伍
  • 如何轻松掌握DamaiHelper:Python自动化抢票完整指南
  • 2026 年 6 月靠谱专业最高人民法院再审律师榜单,五名商事再审律师实务参考 - 外贸老黄
  • SLAM Toolbox终极指南:如何在ROS中实现高效2D建图与终身定位
  • 2026黄岛街道专业的空调移机服务公司哪家靠谱 - 品牌排行榜
  • 2026 年最新榜单!杭州本地哪家 GEO 优化公司效果好?真实实力排行 - 936品牌测评网
  • ComfyUI-KJNodes:工作流优化、模型加速与高级遮罩处理的终极解决方案
  • 如何将封闭智能音箱转变为开源平台:3个核心技术突破方案
  • 2026黄山防水补漏靠谱服务商盘点:屋面/厨卫/外墙/地下室渗水维修详解,适配皖南山区梅雨季多雨雾甄选指南 - 宅安选房屋修缮
  • 统一SerDes建模与信号完整性分析:打破芯片与系统设计壁垒
  • 2026年pvdf管厂家联系方式及行业参考信息 - 品牌排行榜
  • 3分钟搞定小爱音箱音乐服务:终极配置指南让你告别DID烦恼
  • 嵌入式内存控制器UPM原理与配置:从时序控制到工程实践
  • CANN 图引擎 GE 概念拆解:用剧场制片类比深度理解从算子图构建、图优化 Pass 体系、算子调度策略、昇腾硬件映射到可视化调试的完整生命周期
  • 2026承德防水补漏靠谱服务商盘点:屋面/厨卫/外墙/地下室渗水维修详解,适配冀北山地极寒防冻甄选指南 - 宅安选房屋修缮