用-nan比较数组

时间:2019-01-28 01:16:10

标签: arrays swift command-line nan

我有两个元素数量相等的Double数组。三角计算后,它们都包含数字和一些NaN值。

我需要将第一个数组的每个元素与第二个数组的每个元素进行比较,找到更大的数字,然后将其放入新的第三个数组中。最后,第三个数组应包含与第一个或第二个数组相同数量的元素。

如果比较两个Nan,我需要在该确切索引处显示特定的错误消息“可怕的错误”。所以我猜第三个数组应该是String,以便能够同时显示数字和错误消息。如果将Double数与NaN进行比较,则应始终选择Double数。

我该怎么做?

这是我的代码:

import Foundation

var initValue = Double()
var finalValue = Double()
var stepValue = Double()

while true {
    print("Enter the starting number of the range")
    if let number = readLine(), Double(number) != nil {
        initValue = Double(number)!
        break
    } else {
        print("Enter the correct number!")
    }
}

while true {
    print("Enter the end value of the range")
    if let number = readLine(), Double(number) != nil, Double(number)! > initValue {
        finalValue = Double(number)!
        break
    } else {
        print("Enter the correct number, which is greater than starting number of the range!")
    }
}

while true {
    print("Enter delta")
    if let number = readLine(), Double(number) != nil {
        stepValue = Double(number)!
        break
    } else {
        print("Enter the correct number!")
    }
}

var trueArray = [Double]()
for number in stride(from: initValue, through: finalValue, by: stepValue) {
    trueArray.append(number)
}

func calcLn () -> [Double] {
    let calculatedArray = trueArray.map { log(1-46/sin($0)) }

    return calculatedArray
}

func calcTan () -> [String] {
    let calculatedArray = trueArray.map { (tan($0)/46) }

    return calculatedArray
}

1 个答案:

答案 0 :(得分:0)

您可以使用zip并发地遍历2个数组,然后使用map将元素对转换为输出,如您所愿。开启(ln.isNaN, tan.isNaN)并用它来表示各种情况及其结果是有用的。

这是一个艰难的开始:

import Darwin

func promptForDouble(
    initialMessage: String,
    errorMessage: String,
    acceptanceCriteria isAcceptable: (Double) -> Bool = { _ in true }
) -> Double {
    print(initialMessage)

    while true {
        if let number = readLine().flatMap(Double.init), isAcceptable(number) {
            return number
        }

        print(errorMessage)
    }
}

let initValue = promptForDouble(
    initialMessage: "Enter the starting number of the range",
    errorMessage: "Enter the correct number!"
)
let finalValue = promptForDouble(
    initialMessage: "Enter the end value of the range",
    errorMessage: "Enter the correct number, which is greater than starting number of the range!",
    acceptanceCriteria: { initValue < $0 }
)
let stepValue = promptForDouble(
    initialMessage: "Enter delta",
    errorMessage: "Enter the correct number!"
)

// TODO: give these functions better names!
func calcLn(_ input: [Double]) -> [Double] {
    return input.map { log(1 - 46/sin($0)) }
}

func calcTan(_ input: [Double]) -> [Double] {
    return input.map { tan($0) / 46 }
}

func mergeResults(lns: [Double], tans: [Double]) -> [Double?] {
    return zip(lns, tans).map { ln, tan -> Double? in
        switch (ln.isNaN, tan.isNaN) {
            case ( true,  true): return nil // Return nil to express error. Don't introduce Strings yet.
            case (false,  true): return ln
            case ( true, false): return tan
            case (false, false): return max(ln, tan)
        }
    }
}

func printResults(_ a1: [Double], _ a2: [Double], _ a3: [Double?]) {
    for (a, (b, c)) in zip(a1, zip(a2, a3)) {
        let resultString = c.map(String.init) ?? "terrible error" // Note: Strings are only introduced at the UI/presentation layer
        print("ln: \(a),\ttan: \(b),\tresult: \(resultString)") 
    }
}


// TODO: give these arrays better names!

let inputs = Array(stride(from: initValue, through: finalValue, by: stepValue))

let array1 = calcLn(inputs)
let array2 = calcTan(inputs)
let array3 = mergeResults(lns: array1, tans: array2)

printResults(array1, array2, array3)