You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在计算器应用中规避浮点误差,显示正确计算结果

解决计算器浮点误差的显示问题

直接用Double转字符串会暴露二进制浮点存储的固有误差,要实现原生计算器的显示效果,核心是智能判断结果的有效位数,隐藏无意义的近似尾缀,同时保留合理精度。

具体方案

替换你当前的字符串转换逻辑,实现一套格式化逻辑:

  • 优先判断结果是否为整数,是则直接显示整数形式
  • 若不是整数,检查是否存在因浮点误差产生的长串重复尾缀(比如999999或000000),存在则截断到有效部分并修正
  • 对于真正的无限循环小数(如1/3),保留8位小数(和原生计算器对齐)

修改后的代码

struct Air: View {
    
    @State var data: String = "0"
    @State var firstNumber: Double = 0.3
    @State var secondNumber: Double = 3
    @State var result: Double = 0
    
    var body: some View {
        VStack{
            Button("Push"){
                result = calculate(first: firstNumber, second: secondNumber)
                data = formatResult(result) // 替换为格式化函数
            }.frame(width: 80, height: 40)
                .background(Color.gray)
                .foregroundColor(.white)
            Text("result: Double = \(result)")
                .font(.title)
            Text("data: String = \(data)")
                .font(.title)
        }
    }
}

func calculate(first: Double, second:Double) -> Double {
    return first * second
}

// 核心格式化函数
func formatResult(_ number: Double) -> String {
    // 判断是否为整数
    if number.rounded() == number {
        return String(Int(number))
    }
    
    // 转成高精度字符串,用于检测浮点误差尾缀
    let highPrecisionStr = String(format: "%.15f", number)
    
    // 处理999999尾缀(如0.899999999999999 → 0.9)
    if let nineRange = highPrecisionStr.range(of: "999999") {
        let truncatedStr = String(highPrecisionStr[..<nineRange.lowerBound])
        if let truncatedNum = Double(truncatedStr) {
            return cleanFormattedString(truncatedNum + 0.000001)
        }
    }
    
    // 处理000000尾缀(如0.300000000000000 → 0.3)
    if let zeroRange = highPrecisionStr.range(of: "000000") {
        let truncatedStr = String(highPrecisionStr[..<zeroRange.lowerBound])
        if let truncatedNum = Double(truncatedStr) {
            return cleanFormattedString(truncatedNum)
        }
    }
    
    // 正常情况格式化到8位小数
    return cleanFormattedString(number)
}

// 辅助函数:清理末尾无意义的0和小数点
func cleanFormattedString(_ number: Double) -> String {
    let formatted = String(format: "%.8f", number)
    // 正则去掉末尾的0和可能的小数点
    return formatted.replacingOccurrences(of: "\\.?0+$", with: "", options: .regularExpression)
}

效果说明

  • 0.1+0.2会显示为0.3,0.3×3会显示为0.9
  • 1/3会显示为0.33333333
  • 整数结果(如2×3)会显示为6

内容的提问来源于stack exchange,提问作者Yukhnenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 17:17:25