【问题标题】:Round number to nearest "nth" based on first non zero根据第一个非零将数字舍入到最接近的“第 n 个”
【发布时间】:2023-12-29 18:19:01
【问题描述】:

我想将 Double 舍入到小数点后最接近的非零数字。

例如:

x = 0.002341
rounded = 0.002

x = 0.000048123
rounded = 0.00005

对于基数> 0的情况,它应该这样执行

x = 1.000234
rounded = 1.0002

如果我知道位数,我知道我可以使用Double(round(1000*x)/1000),但我希望它适用于任何数字。有没有 swift 函数可以做到这一点?

【问题讨论】:

    标签: ios swift double rounding


    【解决方案1】:

    你可以用对数来解决这个问题:

    func roundFirst(x:Double) -> Double {
        if x == 0 {
            return x;
        }
        let mul : Double = pow(10, floor(log10(abs(x))))
        return round(x/mul)*mul
    }
    

    log10(abs(x)) 的非小数部分为您提供用作乘数的数字的倒数的 10 的正或负幂。 floor 删除分数,pow(10,...) 为您提供一个乘数,用于舍入技巧。

    我在操场上用几个数字试过这个。这是我所拥有的:

    println(roundFirst(0.002341))     // 0.002
    println(roundFirst(0.000048123))  // 5e-05
    println(roundFirst(0.0))          // 0.0
    println(roundFirst(2.6))          // 3.0
    println(roundFirst(123.0))        // 100
    println(roundFirst(-0.002341))    // -0.002
    println(roundFirst(-0.000048123)) // -5e-05
    println(roundFirst(-2.6))         // -3.0
    println(roundFirst(-123.0))       // -100
    

    【讨论】:

    • 很好的解决方案,但不适用于带有尾随小数的数字 > 0,例如:roundFirst(2.0234) 返回 2
    • @mattymcgee 这正是我理解你的问题的方式——我认为你想保留最高值的数字,在2.0234 的情况下是2。如果您只想将此解决方案应用于小数部分,请使用modf 将整体和小数分开,使用roundFirst,然后将两个部分重新组合。
    【解决方案2】:

    例如,您还没有指定x = 1.002341 时发生的情况。根据您的有限情况,您可以使用:

    func myRound (var number : Double) -> Double {
        if number == 0 {
            return number
        }
    
        let integerPart = floor(number)
        var base = 1.0
    
        number -= integerPart
        while abs(number) < 1 {
            number *= 10.0
            base *= 10.0
        }
    
        return integerPart + round(number) / base
    }
    

    【讨论】:

      最近更新 更多