Как проверить значение null при распаковке опций из словаря Swift? [Дубликат]

Нет, не разбит, но большинство десятичных дробей должно быть аппроксимировано

Резюме

Арифметика с плавающей точкой точный, к сожалению, он не очень хорошо сочетается с нашим обычным представлением числа base-10, так что получается, что мы часто даем ему ввод, который немного от того, что мы написали.

Даже простые числа, такие как 0.01, 0.02, 0.03, 0.04 ... 0.24, не представляются точно как двоичные дроби, даже если в мантиссе были тысячи бит точности, даже если у вас были миллионы. Если вы отсчитываете с шагом 0,01, пока вы не достигнете 0,25, вы получите первую фракцию (в этой последовательности), представленную в base10 и base2. Но если вы попытались использовать FP, ваш 0,01 был бы слегка отключен, поэтому единственный способ добавить 25 из них до хорошего точного 0.25 потребовал бы длинной цепи причинности, включающей защитные биты и округление.

Мы постоянно даем аппарату FP что-то вроде простого в базе 10, но это повторяющаяся фракция в базе 2.

Как это произошло?

Когда мы пишем в десятичной форме, каждая дробь является рациональным числом форма

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; x / (2n + 5n).

В двоичном выражении мы получаем только член 2n , то есть:

& nbsp ; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; & NBSP; x / 2n

Итак, в десятичной форме мы не можем представлять 1/3. Поскольку база 10 включает в себя 2 как простой коэффициент, каждое число, которое мы можем записать как двоичную дробь , также может быть записано в виде базовой дроби. Однако вряд ли что-либо, что мы пишем как base10, представляется в двоичном виде. В диапазоне от 0,01, 0,02, 0,03 ... 0,99 только цифры три могут быть представлены в нашем формате FP: 0,25, 0,50 и 0,75, поскольку они равны 1/4, 1/2, и 3/4 - все числа с простым множителем, использующим только 2n-член.

В базе 10 мы не можем представлять 1/3. Но в двоичном коде мы не можем делать 1/10 или 1/3.

Так что, хотя каждая двоичная дробь может быть записана в десятичной системе, обратное неверно. И фактически большинство десятичных дробей повторяются в двоичном формате.

Работа с ним

Разработчикам обычно дают указание & Lt; epsilon , лучшим советом может быть округление до целочисленных значений (в библиотеке C: round () и roundf (), т. е. оставаться в формате FP), а затем сравнивать. Округление до определенной длины десятичной дроби решает большинство проблем с выходом.

Кроме того, при реальных проблемах с хрустом (проблемы, которые FP был изобретен на ранних, ужасно дорогих компьютерах) физические константы Вселенной и все другие измерения известны только относительно небольшому числу значимых цифр, поэтому все пространство проблем было «неточным» в любом случае. FP «точность» не является проблемой в этом виде приложений.

Вся проблема действительно возникает, когда люди пытаются использовать FP для подсчета бобов. Это работает для этого, но только если вы придерживаетесь интегральных значений, какой вид поражает смысл его использования. Вот почему у нас есть все эти библиотеки программного обеспечения с десятичной дроби.

Мне нравится ответ на пиццу от Chris , потому что он описывает фактическую проблему, а не только обычная ручная работа о «неточности». Если бы FP были просто «неточными», мы могли бы исправить , что и сделали бы это несколько десятилетий назад. Причина, по которой у нас нет, - это то, что формат FP компактен и быстр, и это лучший способ хрустить множество чисел. Кроме того, это наследие космической эры и гонки вооружений и ранние попытки решить большие проблемы с очень медленными компьютерами с использованием небольших систем памяти. (Иногда отдельные магнитные сердечники для 1-битного хранилища, но это другая история. )

Заключение

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

5
задан Alex311 15 March 2016 в 18:33
поделиться

2 ответа

Проверка значения словаря nil имеет смысл только в том случае, если значения словаря являются типом Optional, что означает, что вам необходимо ограничить свой метод расширения этим случаем.

Это возможно путем определения протокола, который соответствует всем необязательным типам (сравните . Как написать функцию, которая будет разворачивать общее свойство в swift при условии, что это необязательный тип? , что является лишь небольшой модификацией Создание расширения для фильтрации нильсов из массива в Swift ):

protocol OptionalType {  
    typealias Wrapped 
    var asOptional : Wrapped? { get }
}  

extension Optional : OptionalType {  
    var asOptional : Wrapped? {  
        return self 
    }  
}

Теперь вы можете определить метод расширения, ограниченный словарями необязательных типов значений:

extension Dictionary where Value : OptionalType {

    func test()  {
        for key in self.keys { ... }
    }
}

Как уже объяснил Мэтт, self[key] может быть nil, если этот ключ отсутствует в словаре, и этого здесь не может быть. Поэтому вы всегда можете получить значение для этого ключа

            let value = self[key]! 

внутри этого цикла. Лучше перечислить ключи и значения:

        for (key, value) in self { ... }

Теперь value - значение словаря (для key), и его тип соответствует OptionalType. Используя свойство протокола asOptional, вы получаете опцию, которая может быть протестирована против nil:

             if value.asOptional == nil { ... }

или использована с необязательной привязкой.

Объединяя все это:

extension Dictionary where Value : OptionalType {

    func test()  {
        for (key, value) in self {
            if let unwrappedValue = value.asOptional {
                print("Unwrapped value for '\(key)' is '\(unwrappedValue)'")
            } else {
                print("Value for '\(key)' is nil")
            }
        }
    }
}

Пример:

var dict: [String: AnyObject?] = [
    "foo" : "bar",
    "test": nil
]

dict.test()

Выход:

Value for 'test' is nil
Unwrapped value for 'foo' is 'bar'
3
ответ дан Community 25 August 2018 в 14:31
поделиться

У вас есть беспорядок, потому что словарь, значения которого могут быть nil, представляет вам перспективу с двумя обернутыми опциями , и поэтому два вида nil , Вы получаете nil, если ключ отсутствует, а затем nil, который вы получаете, если ключ не отсутствует, и вы разворачиваете извлеченный результат. И, к сожалению, вы тестируете на детской площадке, которая является плохим местом для изучения различия.

Чтобы понять, что я имею в виду, рассмотрим только следующее:

var d : [String:Int?] = ["Matt":1]
let val = d["Matt"]

Что является типом val? Это Int?? - Int, завернутый в опцию, завернутый в другой Необязательный. Это потому, что значение внутри словаря было, по определению, Int, завернутым в Необязательный, а затем извлечение значения его ключами, что в другое Необязательно.

Итак, давайте немного поработаем и сделаем так:

var d : [String:Int?] = ["Matt":nil]
let val = d["Matt"]

Что такое val? Ну, детская площадка может сказать , что это nil, но правда более сложна; это nil , завернутый в другой Необязательный . Это проще всего увидеть, если вы печатаете val, и в этом случае вы получаете, а не nil, но "Optional(nil)".

Но если мы попробуем что-нибудь, ключ отсутствует, мы получаем другой ответ :

let val2 = d["Alex"]

Это действительно - nil, означающее, что ключ отсутствует. И если мы печатаем val2, получаем "nil". Игровая площадка не делает различия (она говорит nil как для val, так и val2), но преобразование в String (что делает print) показывает разницу.

So часть проблемы - это вся эта двойная упаковка, а другая часть состоит в том, что игровая площадка представляет собой двойную обертку Необязательно очень вводящим в заблуждение способом.

MORAL 1: Словарь, тип значения которого является Необязательно может оказаться очень сложным.

MORAL 2: Игровые площадки - это работа дьявола. Избежать их. Используйте реальное приложение и используйте ведение журнала на консоли или панель переменных отладчика, чтобы узнать, что происходит на самом деле.

7
ответ дан matt 25 August 2018 в 14:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: