消极时,斯威夫特加倍奇怪

Posted

技术标签:

【中文标题】消极时,斯威夫特加倍奇怪【英文标题】:Swift doubly strange when negative 【发布时间】:2017-03-23 07:46:57 【问题描述】:

Xcode 8.2.1、Swift 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 Playground 中运行。)

有没有办法扩展Double以使第二个打印语句按预期工作(而不像第三个打印语句那样使用括号)?

【问题讨论】:

【参考方案1】:

Martin R 是正确的,这是评估顺序的问题,遗憾的是(据我所知)中缀运算符(在本例中为 -)不能指定优先级。我想出的唯一方法是制作自定义插值运算符

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

所以结果是:

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

为了防止直接调用双扩展方法 interpolate 可以将文件私有封装在同一个文件中。

【讨论】:

看来,不管(编码)问题是什么,总有人能解决它!这是一个巧妙的解决方案,尽管它不如将值括在括号中那么明显。我希望运算符不仅限于模糊的数学曲线,还可以是单词。【参考方案2】:

这是一个评估顺序的问题。您的第二个表达式被评估为

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

interpolate()1.0 上被调用,结果被否定。

您必须像在第三个表达式中一样设置显式括号,以便在 -1.0 上调用 interpolate()

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

【讨论】:

感谢您的回答,马丁。我知道评估顺序是问题的原因,但希望有办法解决它。好像没有。 @VinceO'Sullivan:顺便说一句,你的代码有错误,应该是let offset = Double(to.lowerBound)。以0.0.interpolate(from: -5...5, to: -5...5) 为例! 你是对的。我的“从”范围总是从零开始的事实掩盖了这个错误。谢谢。

以上是关于消极时,斯威夫特加倍奇怪的主要内容,如果未能解决你的问题,请参考以下文章

FZU1080 奇怪的数列

RestKit 0.20:restkit 对象映射使属性映射加倍

在界面生成器中更改标签以允许多行视图的宽度加倍

在数组的每个位置获取数组函数加倍值?

斯威夫特:明确表视图是可滚动的

斯威夫特:为啥点击手势识别器不是每次都有效?