仓颉编程语言浮点数保留n位小数(四舍五入)问题及处理
·
仓颉编程语言浮点数保留n位小数(四舍五入)问题及处理
浮点类型包括 Float16、 Float32 和 Float64,分别用于表示编码长度为 16-bit、 32-bit 和 64-bit 的浮点数(带小数部分的数字,如 3.14159、8.24 和 0.1 等)的类型。Float16、 Float32 和 Float64 分别对应 IEEE 754 中的半精度格式(即 binary16)、单精度格式(即 binary32)和双精度格式(即 binary64)。Float64 的精度约为小数点后 15 位,Float32 的精度约为小数点后 6 位,Float16 的精度约为小数点后 3 位。
示例
main() {
println(3.1415926) // 3.141593
var a:Float64 = 3.1415926
println(a) // 3.141593
var b:Float32 = 3.1415926
println(b) //3.141593
var c:Float16 = 3.1415926
println(c) //3.140625,因为Float16 精度不足
}
运行效果:

convert包
仓颉首个长期支持版本(LTS 1.0.0)标准库的convert包(std.convert),提供了类型转换和格式化功能。其中,格式化format函数可以提供给精度处理( 控制 小数点后面的位数)。
示例 使用parse函数常规转换
import std.convert.*
main() {
let a:Float64 = 3.1415926
println(a) // 输出: 3.141593
println("a= ${a.format(".10")}") // 输出:a= 3.1415926000
let b:Float32 = 3.1415926
println(b) // 输出:3.141593
println("b= ${b.format(".10")}") // 输出:b= 3.1415925026
let c:Float16 = 3.1415926
println(c) // 输出:3.140625 ?! 因为Float16 精度不足
println("c= ${c.format(".10")}") // 输出:c= 3.1406250000
}
运行截图

也可以自定义的浮点数保留 n 位小数(四舍五入)函数,源码如下:
// 浮点数保留 n 位小数(四舍五入)
//在7 月推出首个长期支持版本(LTS 1.0.0)通过
// 第一个参数浮点数;第二个参数是小数位数
// 真正的实现只接受 Float64,
func formatFloat(v: Float64, digits: Int64): String {
if (digits <= 0) {
return Int64(v).toString()
}
// 1. 放大 10^n 倍
var scale = 1
for (_ in 0..digits) { scale *= 10 }
// 2. 加 0.5 后截断,实现四舍五入
let scaled = v * Float64(scale)
let rounded = if (scaled >= 0.0) { scaled + 0.5 } else { scaled - 0.5 }
let n = Int64(rounded)
// 3. 拆整数 / 小数
let intPart = (n / scale).toString()
var fracPart = (if (n < 0) { -n } else { n } % scale).toString()
// 4. 左侧补零
while (fracPart.size < digits) { fracPart = "0" + fracPart }
return "${intPart}.${fracPart}"
}
// ---------- 测试 ----------
main() {
println(formatFloat(192.0, 2)) // 192.00
println(formatFloat(123.4, 0)) // 123
println(formatFloat(0.007, 3)) // 0.007
println(formatFloat(-2.5556, 2)) // -2.50
println(formatFloat(3.1415926, 3)) // 3.142
var a:Float64 = 3.1415926
println(formatFloat(a, 3)) // 3.142
var b:Float32 = 3.1415926
println(formatFloat(Float64(b), 3)) //3.142
var c:Float16 = 3.1415926
println(formatFloat(Float64(c), 3)) //3.141 这句为何是3.141而不是3.142,因为Float16 精度不足
}
运行输出:
1192.00
123
0.007
-2.56
3.142
3.142
3.142
3.141
下面给出一个使用自定义formatFloat函数的例子
// 浮点数保留 n 位小数(四舍五入)
//在7 月推出首个长期支持版本(LTS 1.0.0)通过
// 第一个参数浮点数;第二个参数是小数位数
// 真正的实现只接受 Float64
private func formatFloat(v: Float64, digits: Int64): String {
if (digits <= 0) {
return Int64(v).toString()
}
// 1. 放大 10^n 倍
var scale: Int64 = 1
for (_ in 0..digits) { scale *= 10 }
// 2. 加 0.5 后截断,实现四舍五入
let scaled = v * Float64(scale)
let rounded = if (scaled >= 0.0) { scaled + 0.5 } else { scaled - 0.5 }
let n = Int64(rounded)
// 3. 拆整数 / 小数
let intPart = (n / scale).toString()
var fracPart = (if (n < 0) { -n } else { n } % scale).toString()
// 4. 左侧补零
while (fracPart.size < digits) { fracPart = "0" + fracPart }
return "${intPart}.${fracPart}"
}
// 定义 struct 类型
struct Rectangle {
public var width: Float32
public var height: Float32
public init(width: Float32, height: Float32) {
this.width = width
this.height = height
}
public func area() {
width * height
}
}
main() {
// 创建 struct 实例
var r = Rectangle(10.4, 20.6) // r.width = 10.4, r.height = 20.6
let a = r.area()
println("矩形面积是:${a}")
// let a1 = formatFloat(r.area(), 2) // 思考这句为何不可以?
let a1 = formatFloat(Float64(r.area()), 2)
println("矩形面积是:${a1}")
}
运行输出:
矩形面积是:214.239990
矩形面积是:214.24
更多推荐



所有评论(0)