【问题标题】:Sorting Big Int value in Swift在 Swift 中对 Big Int 值进行排序
【发布时间】:2017-08-07 12:30:44
【问题描述】:

我在对一些数字进行排序时遇到问题,这些数字首先是字符串。这些数字对于 UInt64 来说太大了,所以我将字符串数字转换为浮点数,然后对其进行排序。效果很好。但是然后我需要打印这些没有小数的数字。所以我试图格式化数字。但是更大的数字在格式化后会改变它的值。

这是要排序的输入数组 -
["6","31415926535897932384626433832795","1","3","10","3","5"]

我需要以这种格式打印输出 -

1

3

3

5

10

31415926535897932384626433832795

这是我的 swift 代码 -

import Foundation
var a = Array<Float>()
var b = ["6","31415926535897932384626433832795","1","3","10","3","5"]
a = b.map{ Float($0)! }
for i in 0..<(a.count-1){
    var min = i
    for j in (i+1)..<a.count{
        if a[j] < a[min] {
            min = j
        }
    }

    var temp = a[i]
    a[i] = a[min]
    a[min] = temp
}
for val in a{
    print(String(format: "%.0f",val.rounded(.down)))
}

我的输出是 -

1

3

3

5

6

10

31415927314585224784361549725696

如果您注意到最后一个最大的数字与原始输入不同。我们欢迎所有的建议!谢谢!

【问题讨论】:

  • 排序与您的问题无关。如果您在排序之前执行for val in a{ print(String(format: "%.0f",val.rounded(.down)))}(就在b.map{ Float($0)! } 之后),您会注意到同样的问题。
  • 使用Float["6","31415926535897932384626433832797","31415926535897932384626433832796","31415926535897932384626433832795","1", "3"]的排序输出为["1", "3", "6", "31415926535897932384626433832797", "31415926535897932384626433832796", "31415926535897932384626433832795"]。你能接受这个结果吗?
  • stackoverflow.com/questions/30260769/…。这会对你有所帮助。

标签: ios swift sorting


【解决方案1】:

你可以使用数值比较:

let values = ["6","31415926535897932384626433832795","1","3","10","3","5"]

let sortedValues = values.sorted { (value1, value2) in
    let order = value1.compare(value2, options: .numeric)
    return order == .orderedAscending
}

print(sortedValues) // ["1", "3", "3", "5", "6", "10", "31415926535897932384626433832795"]

【讨论】:

  • 游乐场执行失败:错误:MyPlayground.playground:6:17:错误:“字符串”类型的值没有成员“比较”让 order = value1.compare(value2, options: .numeric) ^~~~~~ ~~~~~~~
  • @RichaSrivastava,你需要import Foundation
  • 在 Swift 3 和 Swift 4 环境中测试过,你可能需要Foundation import。
【解决方案2】:

使用浮点数,大整数之间的订单可能会得到意想不到的结果:

var str = "Hello, playground"
let inArray = [
    "6",
    "31415926535897932384626433832797",
    "31415926535897932384626433832796",
    "31415926535897932384626433832795",
    "1",
    "3"
]
let outArray = inArray.sorted {Float($0)! < Float($1)!}
print(outArray)
//->["1", "3", "6", "31415926535897932384626433832797", "31415926535897932384626433832796", "31415926535897932384626433832795"]

如 mag_zbc 的回答中所述,Float 大约只有 7 个有效数字,因此所有较低有效数字都丢失了。

Float("31415926535897932384626433832797") == Float("31415926535897932384626433832795")
//->true

如果您的号码最多为 38 位,您可以使用 Decimal(也建议在 mag_zbc 的回答中)。

let outWithDecimal = inArray.sorted {Decimal(string: $0)! < Decimal(string: $1)!}
print(outWithDecimal)
//->["1", "3", "6", "31415926535897932384626433832795", "31415926535897932384626433832796", "31415926535897932384626433832797"]

否则,如果您的数据包含超过 38 位的数字,String 比较将需要一些预处理:

(假设你所有的数字都是非负整数。)

extension String {
    func fillZeroLeft(_ length: Int) -> String {
        if self.characters.count < length {
            return String.init(repeating: "0", count: length-self.characters.count) + self
        } else {
            return self
        }
    }
}

let maxLen = inArray.lazy.map{$0.characters.count}.max()!
let outWithString = inArray.sorted {$0.fillZeroLeft(maxLen) < $1.fillZeroLeft(maxLen)}
print(outWithString)
//->["1", "3", "6", "31415926535897932384626433832795", "31415926535897932384626433832796", "31415926535897932384626433832797"]

(但 Sulthan 的答案中的数字比较对我来说似乎更好!)

【讨论】:

  • 顺便说一句,你可以简单地先比较长度,而不是用零填充字符串,例如sorted { $0.length &lt; $1.length || $0 &lt; $1 }。 (假设为正整数)。
  • @Sulthan,这似乎是个好主意。但它似乎缺少一些案例。检查您是否可以获得($0, $1) = ("123", "99") 的正确结果。
  • 我错了,应该是$0.length == $1.length ? $0 &lt; $1 : $0.length &lt; $1.length
  • @Sulthan,应该可以。或者{ $0.length &lt; $1.length || $0.length == $1.length &amp;&amp; $0 &lt; $1 } 是等价的。
【解决方案3】:

在 Swift 中使用原始类型准确表示如此大的数字是不可能的。

您的值是 ~3e+32
UInt64 的最大值为 ~1,8e+18
Float 使用 24 位表示有效位,这允许准确表示高达 ~ 的数字1.6e+8 Double 使用 53 位表示有效位,这允许准确表示高达 ~9e+15 的数字

浮点类型(FloatDouble)能够保存更大的值,但它们的精度会超过其有效值所能容纳的数字。

除了使用一些外部库之外,我建议使用 NSDecimalNumber 类,它应该能够容纳多达 38 个十进制数字 - 这对于您的示例中的数字来说已经足够了。但是,如果您需要更大的数字,则需要寻找一些外部库。

【讨论】:

  • 对于浮点数,它是 3.402823e+38 并且有问题的数字小于这个数。
  • 这是Float 可以容纳的最大值,我明确写了我的意思是您可以准确表示的最大数量。
  • 这不是问题。尝试使用 31415926534。这也会失败。
  • 这是意料之中的——你的数字是~3e+11,而Float可以准确表示的最大值是~1.6e+8
猜你喜欢
  • 2014-07-28
  • 1970-01-01
  • 1970-01-01
  • 2015-07-15
  • 1970-01-01
  • 2023-04-07
  • 2017-01-22
  • 2019-01-08
相关资源
最近更新 更多