2017-03-23 4 views
1

のXcode 8.2.1、スウィフト3.彼らは(一見)ほとんどの些細なコードで予期しない問題を明らかにするときスウィフト二重に奇妙な負

import UIKit 

extension Double { 
    /// Linear interpolation. 
    /// Converts a number in one range to its equivalent in another range. 
    func interpolate(from: ClosedRange<Int>, to: ClosedRange<Int>) -> Double { 
     let oldValue = self 
     let offset = Double(to.lowerBound - from.lowerBound) 
     let expansion = Double(to.upperBound - to.lowerBound)/Double(from.upperBound - from.lowerBound) 

     print("\nvalue", oldValue) 
     print("Sign", self.sign) 
     print("offset", offset) 
     print("expansion", expansion) 
     print("oldLowerbound", Double(from.lowerBound)) 

     let newValue = (oldValue - Double(from.lowerBound)) * expansion + offset 
     return newValue 
    } 
} 
print(1.0.interpolate(from: 0...10, to: 50...70)) // Prints 52.0. Correct 
print(-1.0.interpolate(from: 0...10, to: 50...70)) // Prints -52.0. Expected 48.0. 
print((-1.0).interpolate(from: 0...10, to: 50...70)) // Prints 48. Correct. 

ユニットテストは、自分自身のために支払う:

(上記のコードはiOSのプレイグラウンドで実行されます)

Doubleを拡張する方法は、2番目のprint文を期待通りに機能させるためです(3番目のprint文のように大括弧を使用しないでください)。

答えて

1

評価の順序です。あなたの第二の発現は

-(1.0.interpolate(from: 0...10, to: 50...70)) // -52.0 

すなわちinterpolate()として評価されて1.0に呼び出され、その結果が否定されます。

あなたはinterpolate()-1.0に呼び出されるように、あなたの3番目の式のように明示的に括弧を設定する必要があります。

(-1.0).interpolate(from: 0...10, to: 50...70) // 48.0. 
+0

答えていただきありがとうございます。私は評価の順序が問題の原因であることを知っていましたが、その周りに道があることを望んでいました。そうではないようです。 –

+1

@ VinceO'Sullivan:Btw、あなたのコードにエラーがあります。それは 'let offset = Double(to.lowerBound)'でなければなりません。例として '0.0.interpolate(〜:5 ... 5、〜:-5 ... 5)'を試してみてください! –

+0

あなたはそうです。私の "範囲"の範囲が常にゼロで始まったという事実は、そのエラーを隠していました。ありがとう。 –

2

マーティンRが正しいか、それは私の知る限りでは(悲しいことに、評価順序の問題です)中置演算子(この場合は-)に優先順位を指定することはできません。

-1.0 ~| (from: 0...10, to: 50...70) // prints 48 

と直接それがファイル・私的にカプセル化することができ呼ばれるダブル拡張メソッドの補間を防ぐために:私が思いついた唯一の方法は、カスタム補間オペレータ

infix operator ~| 
func ~|(lhs: Double, rhs: (from: ClosedRange<Int>, to: ClosedRange<Int>)) -> Double { 
    return lhs.interpolate(from: rhs.from, to: rhs.to) 
} 

はとても結果があることを確認されます同じファイル。

+0

それは、(コーディング)問題が何であっても、それを解決できる人が常にいるようです。これは巧妙な解決策ですが、大括弧内の値をラップするよりはあまり明白ではありません。私は演算子が漠然とした数学的なくすぐりに限定されていないことを願っていますが、言葉でもあります。 –

関連する問題