Самый простой способ усечь float до 2 знаков после запятой?

Есть ли в Swift способ урезать число с плавающей запятой до 2 знаков после запятой, чтобы вы могли выполнять с ним дальнейшие вычисления? Все потоки, которые я видел, имеют дело с приведением к строке, которую я не могу понять, как затем использовать математически.

Я попытался использовать расширение (найдено на этом форуме), полагая, что после усечения я могу вернуться к float, но в итоге я оказался там, где начал, с другим, не усеченным float. Мне нужно, чтобы возвращаемое значение было в четверть шага (т. е. 6,50, 6,75, 5,25 и т. д.), и в итоге я получаю такие результаты, как 6,990022....

Должен быть простой способ сделать это, но я упираюсь в стену. Заранее спасибо...

Вот проблема:

func roundToNearestQuarter(#power : Float) -> String {

     var errorToLowerQuarterRaw : Float = power % 0.25  // 0.210000038146973

     var errorToLowerQuarterString = errorToLowerQuarterStepRaw.string(2)  // "0.21"

     var errorToLowerQuarter = NSString(string: errorToLowerQuaterStepString).floatValue  // 0.209999993443489

// more code

}

roundToNearestQuater(6.71)

person NoClue    schedule 07.01.2015    source источник
comment
Если в нем есть десятичные разряды, это не float. Swift float является двоичным.   -  person Hot Licks    schedule 08.01.2015


Ответы (2)


Вы не можете округлить Float или Double до двух десятичных цифр точно. Причина в том, что эти типы данных используют двоичное представление с плавающей запятой и не могут точно представлять такие числа, как 0,1 или 0,01. См. например

Но ты сказал:

Мне нужно, чтобы возвращаемое значение было в четверть шага (т.е. 6,50, 6,75, 5,25 и т. д.),

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

Функция round() округляет число с плавающей запятой до ближайшего целого числа. Чтобы округлить до четверти, вам просто нужно «масштабировать» расчет с коэффициентом 4:

func roundToNearestQuarter(num : Float) -> Float {
    return round(num * 4.0)/4.0
}

roundToNearestQuarter(6.71) // 6.75
roundToNearestQuarter(6.6)  // 6.5
person Martin R    schedule 07.01.2015
comment
@Attackfarm: Почему ты так думаешь? Все сказанное в этом ответе верно и для Double. - person Martin R; 03.05.2015
comment
@Attackfarm: Может казаться, что Double хранит все числа точно, потому что println() округляет вывод до 6 знаков после запятой, а Double имеет точность около 15 знаков после запятой. Но попробуй let x = 0.1 ; let y = 0.2 ; println(x + y - 0.3) ... - person Martin R; 05.05.2015
comment
Справедливо. Не знал, что println() имеет это ограничение - person Attackfarm; 05.05.2015
comment
Если вы хотите усечь, округлив в меньшую сторону, используйте floor вместо round - person Nick Yap; 11.09.2015

Если вам нужно работать с настоящей точностью (например, для приложений, связанных с валютой), вы, вероятно, захотите использовать NSDecimalNumber вместо числа с плавающей запятой.

Описанный выше подход можно применить к NSDecimalNumbers, как показано ниже. В этом примере «шаг», до которого вы округляете, может быть любым по вашему выбору, просто установите «приращение» соответствующим образом.

let number: NSDecimalNumber = 100.52
let increment: NSDecimalNumber = 0.25

let handler = NSDecimalNumberHandler(roundingMode: NSRoundingMode.RoundBankers, scale: 0, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false)     // Rounds to the nearest whole number
let result = number.decimalNumberByDividingBy(increment).decimalNumberByRoundingAccordingToBehavior(handler).decimalNumberByMultiplyingBy(increment)

Подробнее об округлении с помощью NSDecimalNumber см. здесь: Как быстро округлить NSDecimalNumber?< /а>

И да, работа с NSDecimalNumber — ужасно многословный способ заниматься математикой, но это не сложно. Если вы обнаружите, что часто выполняете проект с их участием, я рекомендую вам подумать о настройке расширений операторов Swift, чтобы вы могли манипулировать ими более элегантным способом. Посмотрите здесь хороший пример: https://gist.github.com/mattt/1ed12090d7c89f36fd28

person RGood    schedule 21.02.2016