Swift:如何将数组乘以数组(Math:vector by vector)

时间:2016-09-27 12:00:50

标签: arrays swift vector multiplying

我需要将数组乘以另一个数组,就像数学中的向量一样。

例如为: Sub copystatus() Dim LR As Long Dim LC As Integer Dim LB As Long Dim ws As Worksheet Dim ws2 As Worksheet Dim ws3 As Worksheet Dim cLista As String Application.ScreenUpdating = False Application.EnableEvents = False Set ws = ThisWorkbook.sheets("totale") Set ws2 = ThisWorkbook.sheets("liste") LR = ws.Cells(Rows.Count, 5).End(xlUp).Row LC = ws2.Cells(Rows.Count, 2).End(xlUp).Row With ws For x = 2 To LR For i = 2 To LC If .Cells(x, 5).value = ws2.Cells(i, 2).value Then cLista = ws2.Cells(i, 1).value Set ws3 = ThisWorkbook.sheets(cLista) On Error GoTo ErrorHandler LB = ws3.Cells(Rows.Count, 1).End(xlUp).Row ws3.Rows(LB + 1).value = .Rows(x).value ws3.Rows(1).value = .Rows(1).value End If Next i Next x End With Application.ScreenUpdating = True Application.EnableEvents = True ErrorHandler: End Sub A = [1,2,3,4] B = [2,3,4,5]

我甚至无法弄清楚代码,我已经尝试逐个元素地执行此操作,但这对我来说似乎是一个混乱的解决方案,任何想法? (我是swift的初学者)

5 个答案:

答案 0 :(得分:17)

"正在压缩"这两个数组给出了一系列元组(a_i, b_i) 然后可以按元素倍增:

let A = [1,2,3,4]
let B = [2,3,4,5]

let C = zip(A, B).map { $0 * $1 }

print(C) // [2, 6, 12, 20]

(如果数组的长度不同,则zip会静默忽略较长数组的额外元素。)

正如@appzYourLife正确说的那样,你也可以传递乘法 operator直接作为map的参数而不是闭包表达式:

let C = zip(A, B).map(*)

答案 1 :(得分:6)

单指令多数据

如果您的矢量有4个组件,则可以使用iOS提供的超快simd单指令多数据)指令。

它使用CPU执行并行计算。

给出2个Int32

成分的2个向量
import simd

let a = int4(1, 2, 3, 4)
let b = int4(2, 3, 4, 5)

你可以将每个组件相乘

let res = a &* b // int4(2, 6, 12, 20)
  

Martin R 所述,float(s)模块也提供了double(s)simd的数组。

答案 2 :(得分:5)

加速框架

对于向量乘法的主题,另一个替代方案(除the neat simd covered by @appzYourLife's answer之外)正在使用Accelerate framework。在这种情况下,特别是vDSP methods vDSP_vmulvDSP_vmuld

func vDSP_vmul(UnsafePointer<Float>, vDSP_Stride, 
               UnsafePointer<Float>, vDSP_Stride, 
               UnsafeMutablePointer<Float>, vDSP_Stride, vDSP_Length)

func vDSP_vmulD(UnsafePointer<Double>, vDSP_Stride, 
                UnsafePointer<Double>, vDSP_Stride, 
                UnsafeMutablePointer<Double>, vDSP_Stride, vDSP_Length)

例如,后者用于Double值的两个向量的逐元素乘法:

import Accelerate

let a = [1.5, 2.5, 16.5, 7.5, 3.0]
let b = [3.0, 4.5, 0.25, 3.5, 6.25]
var result = [Double](repeating: 0.0, count: a.count)

if a.count == b.count {
    vDSP_vmulD(a, 1, b, 1, &result, 1, vDSP_Length(a.count))
    print(result) // [4.5, 11.25, 4.125, 26.25, 18.75]
}

请注意,使用Accelerate不像其他方法那样用户友好且安全,因为vDSP_vmulD的向量参数被捕获为不安全指针(UnsafePointer<Double>),并且我们有责任确保输入向量具有相同的长度,以及在向量乘以vDSP_vmulD之前正确分配结果向量。

答案 3 :(得分:1)

使用Swift 5,您可以使用以下方法之一来解决您的问题。


#1。使用SIMD vector types

以下Playground示例代码显示了使用SIMD4的逐元素乘法:

let vector1 = SIMD4(1, 2, 3, 4)
let vector2 = SIMD4(2, 3, 4, 5)

let vector3 = vector1 &* vector2
print(vector3) // prints: SIMD4<Int>(2, 6, 12, 20)

请注意,SIMD协议符合ExpressibleByArrayLiteral。因此,您可以使用数组文字初始化向量:

var vector1: SIMD4 = [1, 2, 3, 4]
let vector2: SIMD4 = [2, 3, 4, 5]

vector1 &*= vector2
print(vector1) // prints: SIMD4<Int>(2, 6, 12, 20)

#2。使用符合NumericExpressibleByArrayLiteral协议的自定义类型

您可以构建自己的符合NumericExpressibleByArrayLiteral的自定义类型。以下Playground示例代码展示了如何实现和使用它:

struct Vector {
    let x, y: Int

    init(_ x: Int, _ y: Int) {
        self.x = x
        self.y = y
    }
}
extension Vector: AdditiveArithmetic {
    static var zero: Vector {
        return Vector(0, 0)
    }

    static func +(lhs: Vector, rhs: Vector) -> Vector {
        return Vector(lhs.x + rhs.x, lhs.y + rhs.y)
    }

    static func +=(lhs: inout Vector, rhs: Vector) {
        lhs = lhs + rhs
    }

    static func -(lhs: Vector, rhs: Vector) -> Vector {
        return Vector(lhs.x - rhs.x, lhs.y - rhs.y)
    }

    static func -=(lhs: inout Vector, rhs: Vector) {
        lhs = lhs - rhs
    }
}
extension Vector: ExpressibleByIntegerLiteral {
    init(integerLiteral value: Int) {
        x = value
        y = value
    }
}
import Darwin

extension Vector: Numeric {
    var magnitude: Int {
        // Implement according to your needs
        return Int(Darwin.sqrt(Double(x * x + y * y)))
    }

    init?<T>(exactly source: T) where T : BinaryInteger {
        guard let source = source as? Int else  {
            return nil
        }
        x = source
        y = source
    }

    static func *(lhs: Vector, rhs: Vector) -> Vector {
        return Vector(lhs.x * rhs.y, lhs.y * rhs.x)
    }

    static func *=(lhs: inout Vector, rhs: Vector) {
        lhs = lhs * rhs
    }
}
extension Vector: ExpressibleByArrayLiteral {
    init(arrayLiteral elements: Int...) {
        assert(elements.count == 2, "arrayLiteral should have exactly 2 elements")
        self.x = elements[0]
        self.y = elements[1]
    }
}

用法:

let vector1 = Vector(1, 2)
let vector2 = Vector(2, 3)

let vector3 = vector1 * vector2
print(vector3) // prints: Vector(x: 3, y: 4)
let vector1: Vector = [1, 2]
let vector2: Vector = [2, 3]

let vector3 = vector1 * vector2
print(vector3) // prints: Vector(x: 3, y: 4)

答案 4 :(得分:0)

 let A = [1,2,3,4]
 let B = [2,3,4,5]
 var C = [Int]()

 A.enumerated().forEach{ index, value in
     return C.append(value * B[index])
 }