将双精度数舍入到小数点后一位(去掉小数位)

Posted

技术标签:

【中文标题】将双精度数舍入到小数点后一位(去掉小数位)【英文标题】: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

【问题讨论】:

【参考方案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 值映射到具有所需小数位数的字符串。

以上是关于将双精度数舍入到小数点后一位(去掉小数位)的主要内容,如果未能解决你的问题,请参考以下文章

如何在小数点后将 Dart 中的双精度数舍入到给定的精度?

将双精度转换为双精度,带一位小数和一位小数?

如何优化 spark 函数以将双精度值舍入到小数点后 2 位?

变体浮点到双精度值转换,舍入到小数点后 1 位 [重复]

将浮点数舍入到 N 个小数位

如何在 Torch 的 GPU 上将张量的元素限制/舍入到小数点后 4 位?