Преобразование функции для работы с Double и Float ... используя тип FloatingPoint? - PullRequest
0 голосов
/ 25 февраля 2019

Я видел подобный вопрос на SO, но он не отвечает на все, что я здесь задаю.

У меня есть такая функция:

  func myFunctionDouble (_ valores:[Double] = []) -> Array<Double> {

    let numeroItens = valores.count
    var c = [Double](repeating: 0,
                     count: numeroItens)

    let factor : Double = Double.pi / Double(numeroItens)

    for i in 0..<numeroItens {
      var sum : Double = 0
      for j in 0..<numeroItens {
        sum = sum + valores[j] * cos ((Double(j) + 0.5) * Double(i) * factor)
      }
      c[i] = sum
    }
    return c;
  }

Я хочу преобразовать эту функцию для работы с Double и Float.

Я думал о замене Double на FloatingPoint но он просто не будет работать и выдаст мне кучу ошибок.

Нет FloatingPoint.pi или массив c не может быть объявлен как

var c = [FloatingPoint](repeating: 0, count: numeroItens)

есть способчтобы сделать это?

и более того, как я могу объявить переменную или массив типа FloatingPoint, я имею в виду, что оба Float и Double?

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Добавленный к решению @ rmaddy, вы можете существенно упростить свой код, используя функции более высокого порядка, чтобы удалить все «шумы», вещи, которые необходимы для вычислений, но на самом деле не являются специфичными для ваших вычислений.

func myFunction<T: FloatingPoint>(_ valores:[T] = []) -> Array<T>
    where T: ExpressibleByFloatLiteral, T: Cosineable {
    let factor: T = T.pi / T(valores.count)

    return valores.indices.map { i in
        return valores.enumerated()
            .map { (offset, element) in
                element * ((T(offset) + 0.5) * T(i) * factor).cosine()
            }
            .reduce(0, +)
    }
}

Отсюда вы можете начать лучше обозначать термины и предоставлять больше контекста относительно того, что они делают.

Термин element * ((T(offset) + 0.5) * T(i) * factor).cosine() faaaaarrrrr слишком сложен для одного выражения.Почему 0.5?Что такое factor?Почему мы берем cosine?Это очень неочевидно.Не только незнакомцы с этим кодом не поймут этого, но со временем вы сами забудете об этом и станете «чужим» для кода.

0 голосов
/ 25 февраля 2019

Следуя примеру, изложенному в Ответ Роба на Как использовать универсальный тип FloatingPoint для Float / Double , вы можете сделать следующее:

import Darwin // minimal necessary import
// importing Foundation, AppKit or UIKit also implicitly import Darwin

protocol Cosineable {
    func cosine() -> Self
}

extension Float: Cosineable {
    func cosine() -> Float { return cos(self) }
}

extension Double: Cosineable {
    func cosine() -> Double { return cos(self) }
}

func myFunction<T: FloatingPoint>(_ valores:[T] = []) -> Array<T> where T: ExpressibleByFloatLiteral, T: Cosineable {

    let numeroItens = valores.count
    var c = [T](repeating: 0,
                     count: numeroItens)

    let factor : T = T.pi / T(numeroItens)

    for i in 0..<numeroItens {
        var sum : T = 0
        for j in 0..<numeroItens {
            sum += valores[j] * ((T(j) + 0.5) * T(i) * factor).cosine()
        }
        c[i] = sum
    }
    return c
}
...