Swift 的 pow() 函数不接受双精度数作为参数
Swift's pow() function won't accept Doubles as arguments
我创建了这个 infix operator ^^
作为使用 pow
函数的替代:
infix operator ^^ { associativity left precedence 155 }
func ^^ <T: IntegerLiteralConvertible>(left: T, right: T) -> T {
return pow(left as Double, right as Double)
}
我使用 IntegerLiteralConvertible
协议作为泛型 left
和 right
的类型约束,因为根据我的理解 this diagramm 表明,它基本上包括所有数字类型。
为了使用 pow
函数,我必须将 left
和 right
向下转换为 Double
,我使用 as
运算符.这不是最安全的方法,但这不是重点。
实现函数时this way swift告诉我:
<stdin>:4:12: error: cannot invoke 'pow' with an argument list of type '(Double, Double)'
return pow(left as Double, right as Double)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
现在据我所知 pow
需要两个 Double
作为参数,那么为什么它会抱怨这个?
感谢@Martin R。这来自迄今为止我在 S.O 上发布的唯一 question。
import Cocoa
协议
protocol Fraction { init(_ value:Double) ; var asDouble : Double { get } }
protocol Text { init(_ value:String) ; var asString : String { get } }
扩展程序
extension String : Text { var asString : String { return self } }
extension Double : Fraction { var asDouble : Double { return self } }
extension Float : Fraction { var asDouble : Double { return Double(self) } }
extension CGFloat : Fraction { var asDouble : Double { return Double(self) } }
中缀运算符^^
infix operator ^^ { associativity left precedence 170 }
func ^^<T:IntegerType, U:IntegerType> (var base:T, var power:U) -> T {
if power < 0 { return 0 }
var result: T = 1
if power > 0 {
if power % 2 == 1 { result *= base }
power /= 2
}
while power > 0 {
base *= base
if power % 2 == 1 { result *= base }
power /= 2
}
return result
}
func ^^<T:Fraction, U:Fraction> (base: T, power: U) -> T {
return T(pow(base.asDouble, power.asDouble))
}
func ^^<T:Text, U:IntegerType> (base:T, var power:U) -> T {
if power <= 0 { return "" as T }
if power == 1 { return base as T }
return power > 1 ? {var result = ""; for x in 1...power { result+=base.asString };return result as T}() : "" as T
}
func ^^<T:Text, U:Text> (base:T, var power:U) -> T {
return "" as T
}
测试
println(1 ^^ -1) // "0" Int
println(1 ^^ 0) // "1" Int
println(1 ^^ 1) // "1" Int
println(1 ^^ 2) // "1" Int
println(2 ^^ -1) // "0" Int
println(2 ^^ 0) // "1" Int
println(2 ^^ 1) // "2" Int
println(2 ^^ 2) // "4" Int
println(2 ^^ 8) // "256" Int
println(2 ^^ 16) // "65536" Int
println(2 ^^ 32) // "4294967296" Int
println(2 ^^ 62) // "4611686018427387904"
println(UInt(2) ^^ 8) // "256" UInt
println(UInt64(2) ^^ 8) // "256" UInt64
why is it complaining about this?
因为 pow returns Double
。并且 Double
与 T
不同。错误消息具有误导性,但它的意思是 "Cannot find pow
that accepts (Double, Double)
and returns T
type"
我认为您在 Swift 中误解了 "cast"。 In Swift as
不转换数值类型。
let intVal:Int = 12
let doubleVal:Double = intVal as Double
// ^ [!] error: 'Int' is not convertible to 'Double'
并且如果操作数的类型在编译时不可预测,则无效转换会导致运行时错误:
func foo<T: IntegerLiteralConvertible>(x: T) {
x as Double // <-- Execution was interrupted
}
foo(12 as Int)
相反,我们必须明确 "convert" 它们。见文件:Numeric Type Conversion
let intVal:Int = 12
let doubleVal:Double = Double(intVal)
这只是因为 Double
有 init(_ v: Int)
初始值设定项。以下代码无法编译:
func foo<T: IntegerLiteralConvertible>(x: T) {
Double(x)
// ^~~~~~~~~ [!] error: cannot invoke 'init' with an argument of type 'T'
}
因为Double
没有init<T:IntegerLiteralConvertible>(_ val:T)
初始化器。
所以,如果你想使用pow()
,你必须将T
转换为Double
作为参数,将Double
转换为T
作为返回值价值。对此没有简单的解决方案。
我创建了这个 infix operator ^^
作为使用 pow
函数的替代:
infix operator ^^ { associativity left precedence 155 }
func ^^ <T: IntegerLiteralConvertible>(left: T, right: T) -> T {
return pow(left as Double, right as Double)
}
我使用 IntegerLiteralConvertible
协议作为泛型 left
和 right
的类型约束,因为根据我的理解 this diagramm 表明,它基本上包括所有数字类型。
为了使用 pow
函数,我必须将 left
和 right
向下转换为 Double
,我使用 as
运算符.这不是最安全的方法,但这不是重点。
实现函数时this way swift告诉我:
<stdin>:4:12: error: cannot invoke 'pow' with an argument list of type '(Double, Double)'
return pow(left as Double, right as Double)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
现在据我所知 pow
需要两个 Double
作为参数,那么为什么它会抱怨这个?
感谢@Martin R。这来自迄今为止我在 S.O 上发布的唯一 question。
import Cocoa
协议
protocol Fraction { init(_ value:Double) ; var asDouble : Double { get } }
protocol Text { init(_ value:String) ; var asString : String { get } }
扩展程序
extension String : Text { var asString : String { return self } }
extension Double : Fraction { var asDouble : Double { return self } }
extension Float : Fraction { var asDouble : Double { return Double(self) } }
extension CGFloat : Fraction { var asDouble : Double { return Double(self) } }
中缀运算符^^
infix operator ^^ { associativity left precedence 170 }
func ^^<T:IntegerType, U:IntegerType> (var base:T, var power:U) -> T {
if power < 0 { return 0 }
var result: T = 1
if power > 0 {
if power % 2 == 1 { result *= base }
power /= 2
}
while power > 0 {
base *= base
if power % 2 == 1 { result *= base }
power /= 2
}
return result
}
func ^^<T:Fraction, U:Fraction> (base: T, power: U) -> T {
return T(pow(base.asDouble, power.asDouble))
}
func ^^<T:Text, U:IntegerType> (base:T, var power:U) -> T {
if power <= 0 { return "" as T }
if power == 1 { return base as T }
return power > 1 ? {var result = ""; for x in 1...power { result+=base.asString };return result as T}() : "" as T
}
func ^^<T:Text, U:Text> (base:T, var power:U) -> T {
return "" as T
}
测试
println(1 ^^ -1) // "0" Int
println(1 ^^ 0) // "1" Int
println(1 ^^ 1) // "1" Int
println(1 ^^ 2) // "1" Int
println(2 ^^ -1) // "0" Int
println(2 ^^ 0) // "1" Int
println(2 ^^ 1) // "2" Int
println(2 ^^ 2) // "4" Int
println(2 ^^ 8) // "256" Int
println(2 ^^ 16) // "65536" Int
println(2 ^^ 32) // "4294967296" Int
println(2 ^^ 62) // "4611686018427387904"
println(UInt(2) ^^ 8) // "256" UInt
println(UInt64(2) ^^ 8) // "256" UInt64
why is it complaining about this?
因为 pow returns Double
。并且 Double
与 T
不同。错误消息具有误导性,但它的意思是 "Cannot find pow
that accepts (Double, Double)
and returns T
type"
我认为您在 Swift 中误解了 "cast"。 In Swift as
不转换数值类型。
let intVal:Int = 12
let doubleVal:Double = intVal as Double
// ^ [!] error: 'Int' is not convertible to 'Double'
并且如果操作数的类型在编译时不可预测,则无效转换会导致运行时错误:
func foo<T: IntegerLiteralConvertible>(x: T) {
x as Double // <-- Execution was interrupted
}
foo(12 as Int)
相反,我们必须明确 "convert" 它们。见文件:Numeric Type Conversion
let intVal:Int = 12
let doubleVal:Double = Double(intVal)
这只是因为 Double
有 init(_ v: Int)
初始值设定项。以下代码无法编译:
func foo<T: IntegerLiteralConvertible>(x: T) {
Double(x)
// ^~~~~~~~~ [!] error: cannot invoke 'init' with an argument of type 'T'
}
因为Double
没有init<T:IntegerLiteralConvertible>(_ val:T)
初始化器。
所以,如果你想使用pow()
,你必须将T
转换为Double
作为参数,将Double
转换为T
作为返回值价值。对此没有简单的解决方案。