ここに私のprevious post on Swift optionalsに続く問題の詳細な説明があります。 here,hereとhere与えられたリードにSwift 3でのオプションのチェーン:なぜ1つの例はうまくいくのですか?
おかげで、私は音階の音符の周波数を計算する文字列配列から画分(高調波比用)または小数(セント用)を読み取ることができています。
文字列配列の各要素は、最初に、/
または2つの関数の.
一方を含むかどうかを確認するためにテストされ、次に分数と小数の両方の数がこのtuning file formatで概説規則に準拠して、オプションのチェーンを使用して入力エラーを識別する。
例1および1aは、両方の形式で正しく入力されたデータがどうなるかを示しています。
画分の混合物スケールと(トップダウン)
C D E F G Ab B C’ let tuning = [ "1/1", "193.15686", "5/4", "503.42157", "696.57843", "25/16", "1082.89214", "2/1"]
デバッグ領域の列が入力されたデータを示す小数は、行は出力周波数(L対を示します-r)。
Optional("1/1")
Optional("193.15686")
Optional("5/4")
Optional("503.42157")
Optional("696.57843")
Optional("25/16")
Optional("1082.89214")
Optional("2/1")
[261.62599999999998, 292.50676085897425, 327.03249999999997, 349.91970174951047, 391.22212058238728, 408.79062499999998, 489.02764963627084, 523.25199999999995]
例2 & 3の両方の機能が悪い入力(すなわち、誤って入力されたデータ)にどのように反応するかを示しています。
悪い画分(例えば、欠落分母は、メッセージを出力)
Optional("1/1")
Optional("5/")
User input error - invalid fraction: frequency now being set to 0.0 Hertz
Optional("500.0")
Optional("700.0")
Optional("2/1")
[261.62599999999998, 0.0, 349.22881168708938, 391.99608729493866, 523.25199999999995]
悪い小数が(が報告されていない報告されている、例えばないが700後。 0 - このメッセージを生成するはずである)
Optional("1/1")
Optional("5/4")
Optional("500.0")
Optional("700")
Optional("2/1")
[261.62599999999998, 327.03249999999997, 349.22881168708938, 0.0, 523.25199999999995]
注:オプションにnilが指定されている場合は、レポートに0.0(Hz)が表示されます。これはコードの別の場所に挿入されました(ここでコメントの文脈で説明されています)
一言で言えば問題はありますか?分数の関数はエラーを報告しますが、10進数の関数は不正な入力を検出できません。
どちらの関数も、オプションの連鎖を使用してガードステートメントを使用します。これは不完全な分数で機能しますが、何もせずに関数が小数点以下の入力条件を誤って報告するようにします。コードを徹底的にチェックした後、私はガード・ステートメントに設定した条件に問題があると確信しています。しかし、私はこの権利を得ることができません。誰でも私が間違っていたことを説明できますか?
チューナー。一言で言えば迅速
import UIKit
class Tuner {
var tuning = [String]()
let tonic: Double = 261.626 // frequency of middle C
var index = -1
let centsPerOctave: Double = 1200.0 // mandated by Scala tuning file format
let formalOctave: Double = 2.0 // Double for stretched-octave tunings
init(tuning: [String]) {
self.tuning = tuning
let frequency = tuning.flatMap(doubleFromDecimalOrFraction)
print(frequency)
}
func doubleFromDecimalOrFraction(s: String?) -> Double {
index += 1
let whichNumericStringType = s
print(whichNumericStringType as Any) // eavesdrop on String?
var possibleFrequency: Double?
// first process decimal.
if (whichNumericStringType?.contains("."))! {
possibleFrequency = processDecimal(s: s)
}
// then process fractional.
if (whichNumericStringType?.contains("/"))! {
possibleFrequency = processFractional(s: s)
}
// Insert "0.0" marker. Remove when processDecimal works
let noteFrequency = possibleFrequency
let zeroFrequency = 0.0
// when noteFrequency? is nil, possibleFrequency is set to zeroFrequency
let frequency = noteFrequency ?? zeroFrequency
return frequency // TO DO let note: (index: Int, frequency: Double)
}
func processFractional(s: String?) -> Double? {
var fractionArray = s?.components(separatedBy: "/")
guard let numerator = Double((fractionArray?[0])!.digits),
let denominator = Double((fractionArray?[1])!.digits),
numerator > 0,
denominator != 0,
fractionArray?.count == 2
else
{
let possibleFrequency = 0.0
print("User input error - invalid fraction: frequency now being set to \(possibleFrequency) Hertz ")
return possibleFrequency
}
let possibleFrequency = tonic * (numerator/denominator)
return possibleFrequency
}
func processDecimal(s: String?) -> Double? {
let decimalArray = s?.components(separatedBy: ".")
guard let _ = s,
decimalArray?.count == 2
else
{
let denominator = 1
let possibleFrequency = 0.0
print("User input error (value read as \(s!.digits)/\(denominator) - see SCL format, http://www.huygens-fokker.org/scala/scl_format.html): frequency now being forced to \(possibleFrequency) Hertz ")
return possibleFrequency
}
let power = Double(s!)!/centsPerOctave
let possibleFrequency = tonic * (formalOctave**power)
return possibleFrequency
}
}
extension String {
var digits: String {
return components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
}
}
precedencegroup Exponentiative {
associativity: left
higherThan: MultiplicationPrecedence
}
infix operator ** : Exponentiative
func ** (num: Double, power: Double) -> Double{
return pow(num, power)
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
// test pitches: rational fractions and decimal numbers (currently 'good')
let tuning = ["1/1", "5/4", "500.0", "700.0", "2/1"]
// Diatonic scale: rational fractions
// let tuning = [ "1/1", "9/8", "5/4", "4/3", "3/2", "27/16", "15/8", "2/1"]
// Mohajira: rational fractions
// let tuning = [ "21/20", "9/8", "6/5", "49/40", "4/3", "7/5", "3/2", "8/5", "49/30", "9/5", "11/6", "2/1"]
// Diatonic scale: 12-tET
// let tuning = [ "0.0", "200.0", "400.0", "500", "700.0", "900.0", "1100.0", "1200.0"]
// Diatonic scale: mixed 12-tET and rational fractions
// let tuning = [ "0.0", "9/8", "400.0", "4/3", "700.0", "27/16", "1100.0", "2/1"]
// Diatonic scale: 19-tET
// let tuning = [ "0.0", "189.48", "315.8", "505.28", "694.76", "884.24", "1073.72", "1200.0"]
// Diatonic 1/4-comma meantone scale. Pietro Aaron's temperament (1523) : mixed cents and rational fractions
// let tuning = [ "1/1", "193.15686", "5/4", "503.42157", "696.57843", "25/16", "1082.89214", "2/1"]
override func viewDidLoad() {
super.viewDidLoad()
_ = Tuner(tuning: tuning)
}
}
string = "700"のときprocessDecimal funcをデバッグしましたか?私はdecimalArray.countが何であるか知っていることに興味があります。 –
上に明示的に強制アンラッピング( '!')がたくさんあります。 'processFractional':これは実行時のクラッシュを引き起こす可能性があるため、一般的に避けてください。例えば。 'processFractional(...)'、 'Double((fractionArray?[0])!. digits)'の 'guard 'のために、オプションの連鎖と' nil'合体演算子で安全にすることができます。 'Double((fractionArray?[0])?digits ??" failMe ")'。 – dfri
3つのすべての回答は、以前の質問を解決するにはhttp://stackoverflow.com/a/41337042/2348597、http://stackoverflow.com/a/41337068/2348597、http://stackoverflow.com/a/41359262/2348597強制アンラッピングなしのタスク。 –