【问题标题】:Round a double down to one decimal place (dropping decimal places)将双精度数舍入到小数点后一位(去掉小数位)
【发布时间】:2018-01-26 03:29:23
【问题描述】:

我想将双精度数四舍五入到小数点后 1 位。例如,如果我有一个双 let val = 3.1915,我想将它向下舍入到 3.1。正常的舍入函数会将其舍入到3.2,但我基本上只想去掉剩余的小数位。做这个的最好方式是什么?这有本机功能吗?我知道这很简单,但我想知道在不使用任何解决方法或不良做法的情况下,最好的方法是什么。这不是其他四舍五入问题的重复,因为我不是在问四舍五入,而是在问如何去掉小数位。

同样,如果值为3.1215,它也会四舍五入为3.1

【问题讨论】:

    标签: swift swift4


    【解决方案1】:

    使用函数trunc()(代表截断)将去掉小数部分而不进行四舍五入。具体来说,将Double 的值乘以 10,截断它,然后再除以 10。然后,要使用 1 个小数位显示,请使用 String(format:):

    let aDouble = 1.15
    let truncated = trunc(aDouble * 10) / 10 
    let string = String(format: "%.1f", truncated
    print(string)
    
    (displays "1.1")
    

    或者,处理整个样本值数组:

    让浮动 = 步幅(从:1.099,到:2.0,通过:0.1)

    let truncs = floats
      .map { trunc($0 * 10) / 10 }
      .map { String(format: "%.1f", $0) }
    
    let beforeAndAfter = zip(floats, truncs)
        .map { (float: $0.0, truncString: $0.1)}
    
    beforeAndAfter.forEach { print(String(format: "%.3f truncated to 1 place is %@", $0.0, $0.1)) }
    

    输出:

    1.099 truncated to 1 place is 1.0
    1.199 truncated to 1 place is 1.1
    1.299 truncated to 1 place is 1.2
    1.399 truncated to 1 place is 1.3
    1.499 truncated to 1 place is 1.4
    1.599 truncated to 1 place is 1.5
    1.699 truncated to 1 place is 1.6
    1.799 truncated to 1 place is 1.7
    1.899 truncated to 1 place is 1.8
    1.999 truncated to 1 place is 1.9
    

    【讨论】:

      【解决方案2】:

      通过您的示例,我假设您的意思是您想要截断,如果是这样,使用乘法并转换为 Int 然后除法并转换回 Float/Double 即可。

      示例:3.1915 -> 3.1

      var val = 3.1915
      let intVal:Int = Int(val*10)
      val = Float(intVal)/10.0
      
      print(val) //3.1
      

      如果您想要更多小数位,只需乘以 100 或 1000 即可。

      如果出于任何原因你想使用 round() 函数,有一个接受 FloatingPointRoundingRule 的重载变体,它的工作方式如下:

      var val = 3.1915
      val*=10  //Determine decimal places
      val.round(FloatingPoint.towardZero) // .down is also available which differs in rounding negative numbers.
      val*=0.1  //This is a divide by 10
      
      print(val) //3.1
      

      在实际使用中,我建议创建一个扩展或全局函数,而不是每次都编写这个块。它看起来像:

      extension Float {
          func trunc(_ decimal:Int) {
              var temp = self
              let multiplier = powf(10,decimal) //pow() for Double
              temp = Float(Int(temp*multiplier))/multiplier  //This is actually the first example put into one line
              return temp
          }
      }
      

      并使用:

      var val = 3.1915
      
      print(val.trunc(1))  //3.1
      

      【讨论】:

      • 由于二进制浮点固有的错误,使用print(val) 并不总是能得到想要的结果。最好使用print(String(format:"%.1f", val))
      • True... 但 print 更像是一个调试函数,用于在运行时检查此变量的值,我宁愿拥有精确的值而不是格式化的值,以防出现一些错误-between 导致 val 变为 3.19,这将导致后续计算错误但不会反映在 print() 中。我也同意使用字符串格式来显示用户可见的值,以防止 3.100000001 问题:)
      • 我只是作为插图打印。一个简单的事实是二进制浮点中没有小数位的概念。如果要将十进制数显示为特定的小数位数,则需要使用 String(format:)NumberFormatter 将其转换为字符串,或使用 DecimalNumber 类,它在内部以 10 为基数表示数字,因此它们确实可以存储特定的小数位数。
      • 在我的回答中,我将 Double 值映射到具有所需小数位数的字符串。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      • 2011-08-08
      相关资源
      最近更新 更多