仓颉语言数值运算实战:取模与幂运算、位运算、Min/Max 与 abs、浮点转整数与舍入
文档知识库教程OpenHarmony【免费下载链接】CangjieCorpus本仓库为仓颉编程语言语料库聚焦 仓颉编程语言 核心知识体系整合官方开发指南、API 文档、典型代码示例及语法规范等多维度资源经结构化处理与专业标注构建为支持 RAG检索增强生成技术 的高质量知识基座适配智能编码助手、学习辅助工具等应用开发需求。 欢迎开发者基于本语料库构建仓颉语言智能应用推动鸿蒙开发生态智能化升级项目地址https://gitcode.com/Cangjie/CangjieCorpus点击查看免费下载本文基于仓颉语言语料库中的 Numbers 文档展开系统讲解仓颉中数值运算的几个关键规则取模%与幂运算**的类型约束、一元负号与幂运算的优先级陷阱、以!为按位求反符的位运算体系、通过std.math.*获取整数类型Min/Max与计算绝对值abs以及浮点数转整数时的向零截断与floor/ceil/round三种显式舍入。结合仓库内std.math标准库的 API 文档与语言规范读完本文你可以在仓颉中正确完成数值运算的类型选择、优先级控制、位级操作与浮点舍入转换。数值运算符体系先明确谁支持什么仓颉的整数类型分为有符号Int8、Int16、Int32、Int64、IntNative与无符号UInt8、UInt16、UInt32、UInt64、UIntNative两类编码长度从 8 位到 64 位以及平台相关尺寸详见 整数类型。浮点类型则为Float16、Float32、Float64对应 IEEE 754 的半精度、单精度、双精度格式见 浮点类型。Numbers 文档开宗明义指出整数运算大体上按常规理解即可但有两点需要注意即取模和幂运算的特殊规则取模使用%只支持整数类型幂运算使用**左操作数只允许Int64或Float64左操作数为Int64时右操作数必须为UInt64表达式结果类型为Int64左操作数为Float64时右操作数必须为Int64或Float64表达式结果类型为Float64。这些约束在语言规范 integer.md 中有完整表述与 Numbers 文档完全一致// ** 的左操作数只能为 Int64 类型或 Float64 类型并且 // - 当左操作数类型为 Int64 时右操作数只能为 UInt64 类型表达式的类型为 Int64。 // - 当左操作数类型为 Float64 时右操作数只能为 Int64 类型或 Float64 类型表达式的类型为 Float64。规范同时还说明了整数类型的完整运算符支持面integer.md算术操作符一元负号-、加法、减法-、乘法*、除法/、取模%、幂运算**。其中除一元负号和幂运算外其余操作符要求左右操作数为相同类型%的操作数只支持整数类型位操作符按位求反!、左移、右移、按位与、按位异或^、按位或|且按位与、按位异或、按位或要求左右操作数为相同整数类型关系操作符、、、、、!要求左右操作数为相同整数类型自增/自减和--只能作为一元后缀操作符使用复合赋值操作符、-、*、/、%、**、、、、^、|。另外整数类型字面量支持二进制0b/0B、八进制0o/0O、十进制、十六进制0x/0X四种进制表示可用下划线_作位数分隔符并可用后缀如100i8、0x10u64显式指定类型浮点字面量则可用f16/f32/f64后缀指定精度。字面量值超出目标类型表示范围时编译器会直接报错例如let x: Int8 128编译失败。优先级陷阱一元负号高于幂运算Numbers 文档中一个经典的反直觉点一元负号-的优先级高于幂运算**。这一点可以在仓颉操作符优先级表中得到印证operator.md优先级数值越小越高操作符优先级含义示例结合方向!3按位求反、逻辑非!expr右结合-3一元负号-expr右结合**4幂运算expr ** expr右结合*,/5乘法除法expr * expr,expr / expr左结合%5取模expr % expr左结合由于一元负号优先级 3比**优先级 4更先结合-10**4实际被解析为-(10**4)……不恰恰相反是解析为(-10)**4的等价效果——负号先作用于10得到-10再对-10做 4 次幂结果是正的10000。Numbers 文档给出的原始示例如下main() { println(-10**4) //10000 println(-(10**4)) //-10000 }运行结果是第一行打印10000第二行打印-10000。因此文档建议当期望先求幂、再取负时必须显式加括号如-(10**4)。这一行为与 Python-10**4 -10000不同从 C/Java-10**4甚至需要括号或编译受限迁移来的开发者尤其需要注意。位运算!是按位求反不是~Numbers 文档指出位与、位或沿用其他语言的和|但位求反使用!符号而不是~。原文示例main() { let a: UInt8 5 //00000101 let b: UInt8 9 //00001001 println(Bitwise NOT of a: ${!a}) // 11111010 println(Bitwise AND of a and b: ${a b}) // 00000001 println(Bitwise OR of a and b: ${a | b}) // 00001101 }逐位验证500000101求反得11111010UInt8下即十进制2505 9只有最低位同为 1得000000015 | 9得00001101十进制13。从标准库源码结构看这套位运算符是通过std.math包中的泛型接口 IntegerT 以操作符扩展extend方式注入各整数类型的public interface IntegerT : NumberT { static func isSigned(): Bool operator func %(rhs: T): T operator func (rhs: T): T operator func |(rhs: T): T operator func ^(rhs: T): T operator func !(): T operator func (n: Int64): T operator func (n: Int64): T }接口声明了%、、|、^、!、、八个操作符并通过extend Int8 : IntegerInt8、extend UInt64 : IntegerUInt64等形式扩展到Int8Int64、IntNative、UInt8UInt64、UIntNative全部整数类型。每个IntN扩展的isSigned()总是返回trueUIntN扩展的总是返回false——这是判断类型有符号性的官方入口。几个使用要点!在仓颉中同时承担逻辑非作用于Bool和按位求反作用于整数两个语义具体含义由操作数类型决定见 operator.md 中!的含义按位求反、逻辑非除、|外还有按位异或^与移位、其中移位的位移量参数类型为Int64、^、|要求左右操作数为相同的整数类型跨类型位运算需先显式转换。整数类型的 Min 与 Max用std.math.*获取边界值Numbers 文档说明导入std.math.*后可以通过属性Min和Max访问各整数类型的最小值与最大值。原文示例import std.math.* main() { println(${Int32.Min}) // -2147483648 println(${Int32.Max}) // 2147483647 println(${UInt32.Min}) // 0 println(${UInt32.Max}) // 4294967295 }输出结果-2147483648 2147483647 0 4294967295在std.math的 API 文档中MaxMinValueT 接口提供了getMax()与getMin()两个静态方法并通过extend Int32 : MaxMinValueInt32、extend UInt32 : MaxMinValueUInt32等方式扩展到各数值类型Min/Max属性即该接口能力的对外呈现接口方法名为getMax/getMin属于 API 层面的对应实现。各整数类型的理论表示范围来自 integer.md与上例相互印证类型表示范围Int8-128 ~ 127Int16-32,768 ~ 32,767Int32-2,147,483,648 ~ 2,147,483,647Int64-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807UInt80 ~ 255UInt160 ~ 65,535UInt320 ~ 4,294,967,295UInt640 ~ 18,446,744,073,709,551,615IntNative/UIntNative平台相关在类型选择上规范给出的建议是在Int64适合的情况下首选Int64因为无类型上下文的整数字面量默认推断为Int64可以避免不必要的类型转换。abs 绝对值注意有符号整数最小值的溢出边界Numbers 文档指出导入std.math.*后使用abs求绝对值import std.math.* main() { println(${abs(-3)}) // 3 }在 std.math 函数 API 中abs提供了Int8、Int16、Int32、Int64以及Float16、Float32、Float64共 7 个重载。其中整数重载有一个容易踩坑的边界异常当输入参数是有符号整数的最小值如Int32.Min时抛出OverflowException。原因是-Int32.Min超出Int32表示范围2147483648 2147483647绝对值无法在同一类型内表达。API 文档给出的异常示例math_package_funcs.mdimport std.math.abs main(): Unit { try { let n Int16(-2 ** 15) // 即 Int16.Min let abs: Int16 abs(n) println(abs) } catch (e: OverflowException) { println(异常输入参数是有符号整数的最小值) } }运行结果异常输入参数是有符号整数的最小值对于不想处理异常的调用方std.math还提供了checkedAbs系列函数如checkedAbs(Int16): OptionInt16入参是该类型最小值时返回None否则返回Some(abs(x))可以用Option优雅地处理这个边界。浮点数转整数T(e)截断语义与 floor/ceil/roundT(e)显式转换向零截断Numbers 文档说明将浮点数转换为整数使用Int64(s)这样的语法按需更换目标类型该转换向零toward zero截断并给出示例println(Int64(3.4)) // prints 3 println(Int64(3.6)) // prints 4这里需要指出一个细节原文第二行的注释// prints 4与其声明的向零截断规则不一致——按截断规则Int64(3.6)的结果应为3。语言规范 类型转换 中数值类型之间的转换一节明确仓颉支持T(e)语法得到值等于e、类型为T的值且其中Int64(1024.1024)的实际运行结果为1024与向零截断语义一致。因此以规则为准Int64(3.6)应得3Int64(-3.6)得-3。原文此处注释可视为笔误读者应以向零截断这一规则描述为准。此外规范还提醒类型转换时可能发生溢出若溢出可被编译器提前检测出则编译器直接报错否则按默认溢出策略在运行时抛出异常typecast.md。由于仓颉不支持跨类型隐式转换任何浮点变整数都必须显式写出T(e)。floor、ceil、round三种显式舍入为了获得比向零截断更精细的舍入控制导入std.math.*后可使用floor、ceil、round。这三个函数返回的仍是浮点数需要再套一层Int64(.)才能得到整数。Numbers 文档的完整示例println(Int64(3.4)) // prints 3 println(Int64(-3.6)) // prints -3 println(Int64(ceil(3.4))) // prints 4 println(Int64(ceil(-3.4))) // prints -3 println(Int64(floor(3.4))) // prints 3 println(Int64(floor(-3.4))) // prints -4 println(Int64(round(3.4))) // prints 3 println(Int64(round(-3.4))) // prints -3 println(Int64(round(-3.6))) // prints -4三个函数的行为对照以3.4/-3.4为例函数语义3.4-3.4Int64(x)直接转换向零截断3-3ceil向上取整朝 ∞4-3floor向下取整朝 -∞3-4roundIEEE-754 向最近舍入3-3在 std.math 函数 API 中可以看到这三个函数均为三个浮点精度的重载签名形如public func ceil(x: Float64): Float64、public func floor(x: Float64): Float64、public func round(x: Float64): Float64返回值类型与入参一致——这正是仍需再套一层Int64(.)的根源。其中round的功能描述值得特别留意此函数采用 IEEE-754 的向最近舍入规则计算浮点数的舍入值。如果该浮点数有两个最近整数则向偶数舍入。也就是说round是四舍六入五取偶银行家舍入而非日常理解的四舍五入API 文档示例中round(1.5)返回2.0000002 为偶数。如果需要真正的四舍五入可以参照std.math的舍入规则枚举 RoundingMode它定义了 6 种规则Ceiling向 ∞、Down向零、Floor向 -∞、HalfEven银行家舍入、HalfUp四舍五入、Up远离零其对照表如7.5 → HalfUp: 8, HalfEven: 8; 4.5 → HalfUp: 5, HalfEven: 4可以作为理解round行为差异的直接参照。小结与延伸阅读把 Numbers 文档的六个知识点串起来仓颉数值运算的实操清单是%仅用于整数**的左操作数只认Int64/Float64且右操作数类型随之被约束一元负号优先级高于**先幂后负必须写括号-(10**4)位求反是!而非~位运算操作数必须同类型可辅以IntegerT接口的isSigned()判断符号性import std.math.*后用Int32.Min/Int32.Max取边界值与Int8~UInt64的表示范围表一一对应abs对有符号整数最小值会抛OverflowException边界敏感场景可改用checkedAbs的Option返回值Int64(x)转换是向零截断要向上/向下/向最近舍入分别组合ceil/floor/round再显式转整数并注意round是向偶舍入。更多材料可在仓库中继续深入std.math 包总览常数定义、浮点数判断与规整、位运算、数学函数、gcd/lcm 等完整能力清单std.math 函数 APIabs、ceil、floor、round、checkedAbs、clamp、gcd、lcm、rotate等全部函数的签名、参数、异常与运行结果std.math 接口 APIIntegerT、FloatingPointT、MaxMinValueT、NumberT等接口定义std.math 枚举 APIRoundingMode六种舍入规则及对照表数学基础运算示例clamp、gcd、lcm、rotate的完整可运行示例与输出整数类型 / 浮点类型 / 基本运算符类型范围、字面量与运算符规范的完整描述操作符附录全部操作符的优先级与结合性总表类型转换T(e)显式转换规则与溢出行为说明。赞分享文档知识库教程OpenHarmony【免费下载链接】CangjieCorpus本仓库为仓颉编程语言语料库聚焦 仓颉编程语言 核心知识体系整合官方开发指南、API 文档、典型代码示例及语法规范等多维度资源经结构化处理与专业标注构建为支持 RAG检索增强生成技术 的高质量知识基座适配智能编码助手、学习辅助工具等应用开发需求。 欢迎开发者基于本语料库构建仓颉语言智能应用推动鸿蒙开发生态智能化升级项目地址https://gitcode.com/Cangjie/CangjieCorpus点击查看免费下载相关推荐TiXL 基础浮点运算运算符实战指南Lib.numbers.float.basic 加减乘除、取模与幂运算全解析TiXL 基础浮点运算运算符实战指南Lib.numbers.float.basic 加减乘除、取模与幂运算全解析 TiXL即本仓库对应的实时动态图形创作工具音视频图形学桌面应用ngxtop指标计算精度浮点数运算与四舍五入策略完全指南ngxtop指标计算精度浮点数运算与四舍五入策略完全指南 ngxtop是一个强大的Nginx服务器实时监控工具它能够解析访问日志并提供类似top命令的实时指运维可观测性CLIConvey实战构建订单-定价-配送微服务系统的完整案例Convey实战构建订单 定价 配送微服务系统的完整案例 Convey是一个为.NET Core微服务设计的简单框架提供了构建微服务所需的核心组件和最佳实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考