使数组的所有值为负数或更改符号

Pat*_*Pat 3 arrays swift

在SWIFT中,有一种快速有效的方法可以使数组的所有值都改变符号(正值变为负值,反之亦然)?

例如:

let x: [Double] =  [1.0, 2.0, -3.0, 4.0, -5.0]
Run Code Online (Sandbox Code Playgroud)

应该成为:

// x = [-1.0, -2.0, 3.0, -4.0, 5.0]
Run Code Online (Sandbox Code Playgroud)

Mar*_*n R 5

如果您需要大型阵列的快速解决方案,那么您可以使用 cblas_dscal()Accelerate框架中的("标量乘法,双精度"):

import Accelerate 

var x = [1.0, 2.0, -3.0, 4.0, -5.0]
cblas_dscal(Int32(x.count), -1.0, &x, 1)

print(x) // [-1.0, -2.0, 3.0, -4.0, 5.0]
Run Code Online (Sandbox Code Playgroud)

备注:也有cblas_sscal()对于Float阵列("单精度").

性能比较:这是一个非常简单的各种方法的性能比较:

let N = 1_000_000 // # of array elements
let R = 100 // # of repetitions

func test1() {
    var x = (0..<N).map { _ in drand48() }
    let start = Date()
    for _ in 0..<R {
        for i in x.indices { x[i] = -x[i] }
    }
    let time = Date().timeIntervalSince(start)
    print("x[i] = -x[i]     ", time)
}

func test2() {
    var x = (0..<N).map { _ in drand48() }
    let start = Date()
    for _ in 0..<R {
        for i in x.indices { x[i].negate() }
    }
    let time = Date().timeIntervalSince(start)
    print("x[i].negate()    ", time)
}

func test3() {
    var x = (0..<N).map { _ in drand48() }
    let start = Date()
    for _ in 0..<R {
        x = x.map { -$0 }
    }
    let time = Date().timeIntervalSince(start)
    print("x.map { -$0 }    ", time)
}

func test4() {
    var x = (0..<N).map { _ in drand48() }
    let start = Date()
    for _ in 0..<R {
        cblas_dscal(Int32(x.count), -1.0, &x, 1)
    }
    let time = Date().timeIntervalSince(start)
    print("cblas_dscal      ", time)
}

test1()
test2()
test3()
test4()
Run Code Online (Sandbox Code Playgroud)

结果(在3.5 GHz Intel iMac上,在Release配置中编译和运行:)

x[i] = -x[i]      0.0492849946022034
x[i].negate()     0.0635690093040466
x.map { -$0 }     0.285757005214691
cblas_dscal       0.0506410002708435

事实证明,cblas_dscal()与x[i] = -x[i]or 的显式循环速度大致相同x[i].negate(),但速度明显快于map()方法.

当然,结果可能在不同的硬件上或与其他阵列大小不同.

像往常一样,从您最熟悉的方法开始,如果事实证明性能至关重要,则寻找更快的方法.