Цель C против Swift математические операции - PullRequest
0 голосов
/ 28 августа 2018

Выполнение следующей операции в Objective-C и Swift возвращает разные результаты:

С входом 23492.4852,

Функция Objective-C:

+ (double)funTest:(double)a {
    return a - (int) a / 360 * 360;
}

возвращает 92,48521

Функция Swift:

class func funTest(a: Double) -> Double {
    return a - Double(Int(a)) / 360 * 360
}

возвращает 0,48521

Кто-нибудь знает, почему разница?

Ответы [ 3 ]

0 голосов
/ 28 августа 2018

Разница между целым числом и делением с плавающей запятой. При целочисленном делении дробная часть игнорируется. Некоторые быстрые примеры: 1 / 2 = 0 или 2 / 3 = 0, но 1.0 / 2.0 = 0.5 и 2.0 / 3.0 = 0.67.

Давайте разберем, как ваш код работает на обоих языках:

Objective-C

Предполагая a = 23492.4852:

a - (int) a / 360 * 360 = a - ((int) a) / 360 * 360
                        = a - 23492 / 360 * 360     // integer division
                        = a - 65 * 360
                        = 23492.4852 - 23400
                        = 92.4852

Objective-C наследует правила продвижения типа от C, что может быть очень запоминающимся.

Swift

Предположим, a = 23492.4852:

a - Double(Int(a)) / 360 * 360 = a - Double(23492) / 360 * 360  // floating point division
                               = a - 65.2556 * 360
                               = a - 23492
                               = 23492.4852 - 23492
                               = 0.4852

В обоих случаях у компилятора есть некоторые возможности для интерпретации литеральной константы 360: ее можно увидеть int или double.

  • Я не знаю точную внутреннюю работу компилятора ObjC. Вы просто должны быть осторожны при смешивании числовых типов в C.
  • Swift пытается предотвратить эту путаницу, заставляя все операнды иметь один и тот же тип данных. Поскольку a равно Double, единственный способ интерпретировать 360 состоит в том, что оно также должно быть Double.
0 голосов
/ 29 августа 2018

Кто-нибудь знает, почему разница?

Вы только что совершили простую ошибку группировки.

Как вы выяснили, Objective-C и Swift требуют преобразования при преобразовании значения с плавающей запятой в целое, поэтому вы написали (int)a для первого и Int(a) для последнего.

Вы также поняли, что преобразование целого числа в значение с плавающей запятой различается в двух языках, в Objective-C (и C, и во многих других языках) преобразование является неявным , тогда как в Swift это явно.

Единственная ошибка, которую вы допустили, это анализ Objective-C и, следовательно, создание неправильного Swift или , вы просто неправильно набрали Swift.

В арифметических выражениях операторы оцениваются в соответствии с приоритетом, соответствующим вашей задаче. Приведения тесно связаны со следующим выражением, затем выполняется умножение и деление, затем сложение и вычитание. Что это значит, ваша Цель-C:

a - (int) a / 360 * 360

анализируется как:

a - (double) ( (int) a / 360 * 360 )

обратите внимание, что приведение (double) применяется к результату выражения (int) a / 360 * 360. То, что вы написали в Swift:

a - Double(Int(a)) / 360 * 360

, что не то же самое, здесь приведение применяется только к Int(a). То, что вы должны были написать:

a - Double(Int(a) / 360 * 360)

, который применяет приведение к Int(a) / 360 * 360 так же, как Objective-C.

С этим исправлением в обоих языках умножение и деление работают на целые числа, а целочисленное деление усекается (например, 9/4 равно 2, а не 2,25). С неуместными круглыми скобками в Swift все умножение и деление работают на значениях с плавающей точкой.

TL; DR: Вы только что поставили круглые скобки.

НТН

0 голосов
/ 28 августа 2018

Это связано с тем, как компиляторы видят числа. Заметьте, что в swift вы должны были явным образом привести a в двойное число после преобразования в Int? Быстрый компилятор видит все выражение как Double s, поэтому, когда вы делаете Double(Int(a)) / 360 * 360, вы получаете 23492 / 360 * 360 = 65.25555... * 360 = 23492.4852. Однако в C / C ++ / Obj-C и т. Д. Он видит, что 23492 / 360 - это деление типа int, дающее 23492 / 360 * 360 = 65 * 360 = 23400. И вот откуда берется 90 (из-за потери точности при делении 2 int с на C.

...