如何编写一个函数来对 n 维向量进行点积?
How to write a function to do the dot product on n-dimensional vector?
首先,这里有一个关于 dot product 是什么的简短提示。
我希望能够有一段代码,我可以按以下方式使用它:
let x = Vector<Double>(dimensions: 3)
let y = Vector<Double>(dimensions: 3)
//...
//assign some values (coordinates) to x and y
//x.dotProduct(y)
如何将 dotProduct
实现为 class 方法?
以下是无效的:
func dot(vector: Point<T>) -> Double {
var sum: Double = 0.0
for index in 0...vector.size {
sum += sum + vector[index] * point[index]
}
}
错误信息是:
error: cannot invoke '*' with an argument list of type '(@lvalue T, $T14)'
新 func dot
:
func dot(vector: Point<T>) -> T {
var sum = 0 as T
println(point.count)
for index in 0..<point.count{
println(vector[index])
println(point[index])
sum += vector[index] * point[index]
}
return sum
}
更新 4:
这个有效:
class Vector<T: SummableMultipliable> {
var dimensions: Int
var coordinates: [T]
init(dimensions: Int) {
self.dimensions = dimensions
self.coordinates = [T](count: dimensions, repeatedValue: 0 as T)
}
func dotProduct<T>(vector: Vector<T>) -> T {
assert(self.dimensions == vector.dimensions, "Vectors don't have the same dimensions.")
//as @AirspeedVelocity suggested:
return reduce(Zip2(self.coordinates, vector.coordinates), 0) { sum, pair in sum + pair.0 * pair.1 }
//the old version:
/*var sum: T = 0
for dimension in 0..<self.dimensions {
sum = sum + (self.coordinates[dimension] as T * vector.coordinates[dimension])
}
return sum*/
}
}
protocol SummableMultipliable: Equatable, IntegerLiteralConvertible {
func +(lhs: Self, rhs: Self) -> Self
func *(lhs: Self, rhs: Self) -> Self
}
extension Int: SummableMultipliable { }
extension Double: SummableMultipliable { }
var x = Vector<Int>(dimensions: 3)
var y = Vector<Int>(dimensions: 3)
x.coordinates[0] = 3
x.coordinates[1] = 2
x.coordinates[2] = 1
y.coordinates[0] = 3
y.coordinates[1] = 2
y.coordinates[2] = 1
println(x.dotProduct(y)) //prints 14
首先,这里有一个关于 dot product 是什么的简短提示。
我希望能够有一段代码,我可以按以下方式使用它:
let x = Vector<Double>(dimensions: 3)
let y = Vector<Double>(dimensions: 3)
//...
//assign some values (coordinates) to x and y
//x.dotProduct(y)
如何将 dotProduct
实现为 class 方法?
以下是无效的:
func dot(vector: Point<T>) -> Double {
var sum: Double = 0.0
for index in 0...vector.size {
sum += sum + vector[index] * point[index]
}
}
错误信息是:
error: cannot invoke '*' with an argument list of type '(@lvalue T, $T14)'
新 func dot
:
func dot(vector: Point<T>) -> T {
var sum = 0 as T
println(point.count)
for index in 0..<point.count{
println(vector[index])
println(point[index])
sum += vector[index] * point[index]
}
return sum
}
更新 4:
这个有效:
class Vector<T: SummableMultipliable> {
var dimensions: Int
var coordinates: [T]
init(dimensions: Int) {
self.dimensions = dimensions
self.coordinates = [T](count: dimensions, repeatedValue: 0 as T)
}
func dotProduct<T>(vector: Vector<T>) -> T {
assert(self.dimensions == vector.dimensions, "Vectors don't have the same dimensions.")
//as @AirspeedVelocity suggested:
return reduce(Zip2(self.coordinates, vector.coordinates), 0) { sum, pair in sum + pair.0 * pair.1 }
//the old version:
/*var sum: T = 0
for dimension in 0..<self.dimensions {
sum = sum + (self.coordinates[dimension] as T * vector.coordinates[dimension])
}
return sum*/
}
}
protocol SummableMultipliable: Equatable, IntegerLiteralConvertible {
func +(lhs: Self, rhs: Self) -> Self
func *(lhs: Self, rhs: Self) -> Self
}
extension Int: SummableMultipliable { }
extension Double: SummableMultipliable { }
var x = Vector<Int>(dimensions: 3)
var y = Vector<Int>(dimensions: 3)
x.coordinates[0] = 3
x.coordinates[1] = 2
x.coordinates[2] = 1
y.coordinates[0] = 3
y.coordinates[1] = 2
y.coordinates[2] = 1
println(x.dotProduct(y)) //prints 14