как выполнить проверку логического результата после назначения в котлин? [Дубликат]

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

Так как это вопрос, связанный с языком, ему нужны языковые агностические инструменты, такие как как Десятичный преобразование с плавающей запятой .

Применяя его к числам в вопросе, рассматриваемым как удваивает:

0,1 преобразуется в 0,1000000000000000055511151231257827021181583404541015625,

0,2 преобразуется в 0.200000000000000011102230246251565404236316680908203125,

0,3 конвертируется в 0,29999999999999999989897769753748434595763683319091796875 и

0,30000000000000004 преобразуется в 0,3000000000000000444089209850062616169452667236328125.

Добавление первых двух чисел вручную или в десятичный калькулятор, такой как Full Precision Calculator , показывает точную сумму фактических входов: 0.3000000000000000166533453693773481063544750213623046875.

Если округлить до эквивалента 0,3, ошибка округления будет 0.0000000000000000277555756156289135105907917022705078125. Округление до эквивалента 0,30000000000000004 также дает ошибку округления 0,0000000000000000277555756156289135105907917022705078125.

Возвращаясь к конвертеру с плавающей запятой, необработанный шестнадцатеричный показатель для 0.30000000000000004 равен 3fd3333333333334, который заканчивается четной цифрой и, следовательно, является правильным результатом.

19
задан hotkey 27 April 2016 в 11:57
поделиться

5 ответов

Как правильно указано @AndroidEx, присваивания не являются выражениями в Kotlin, в отличие от Java. Причина в том, что выражения с побочными эффектами обычно обескуражены. См. это обсуждение по аналогичной теме.

Одно из решений состоит в том, чтобы разделить выражение и перенести присвоение из блока условий:

a = b
if (a != c) { ... }

Другое один из них - использовать функции из stdlib, такие как let , который выполняет лямбда с приемником в качестве параметра и возвращает результат лямбда. apply и run имеют схожую семантику.

if (b.let { a = it; it != c }) { ... }

if (run { a = b; b != c }) { ... }

Благодаря inlining это будет так же эффективно, как и обычный код взятый из лямбда.


Ваш пример с InputStream будет выглядеть как

while (input.read(bytes).let { tmp = it; it != -1 }) { ... }

. Также рассмотрите функцию readBytes для чтения a ByteArray из InputStream.

20
ответ дан hotkey 28 August 2018 в 23:39
поделиться

простой способ в котлине

if (kotlin.run{ a=b; a != c}){ ... }
0
ответ дан Ara Hakobyan 28 August 2018 в 23:39
поделиться

Присвоения не являются выражениями в Kotlin, поэтому вам нужно сделать это снаружи:

var a: Int? = 1
var b: Int? = 2
var c: Int? = 1

a = b
if (a != c)
    print(true)

Для вашего другого примера с InputStream вы могли бы сделать:

fun readFile(path: String) {
    val input: InputStream = FileInputStream(path)
    input.reader().forEachLine {
        print(it)
    }
}
11
ответ дан Community 28 August 2018 в 23:39
поделиться

Я думаю, это может вам помочь:

 input.buffered(1024).reader().forEachLine {
            fos.bufferedWriter().write(it)
        }
0
ответ дан user2944157 28 August 2018 в 23:39
поделиться

Как почти все здесь отметили, присваивания не являются выражениями в Котлине. Однако мы можем принуждать присваивание к выражению, используя литерал функции:

val reader = Files.newBufferedReader(path)
var line: String? = null
while ({ line = reader.readLine(); line }() != null) {
    println(line);
}
7
ответ дан w.brian 28 August 2018 в 23:39
поделиться
Другие вопросы по тегам:

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