недопустимый синтаксис при использовании питонического стиля для кода if, else statement [duplicate]

Просто для удовольствия я играл с представлением поплавков, следуя определениям из стандарта C99, и я написал код ниже.

Код печатает двоичное представление поплавков в 3 отдельных группах

SIGN EXPONENT FRACTION

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

Поэтому, когда вы пишете float x = 999... компилятор преобразует это число в битовое представление, напечатанное функцией xx, так что сумма, напечатанная функцией yy, будет равна заданному числу.

В действительности эта сумма является только приближение. Для числа 999,999,999 компилятор будет вставлять в бит представление float число 1,000,000,000

После кода я присоединяю консольный сеанс, в котором я вычисляю сумму терминов для обеих констант (минус PI и 999999999) который действительно существует в аппаратном обеспечении, вставленном там компилятором.

#include <stdio.h>
#include <limits.h>

void
xx(float *x)
{
    unsigned char i = sizeof(*x)*CHAR_BIT-1;
    do {
        switch (i) {
        case 31:
             printf("sign:");
             break;
        case 30:
             printf("exponent:");
             break;
        case 23:
             printf("fraction:");
             break;

        }
        char b=(*(unsigned long long*)x&((unsigned long long)1<<i))!=0;
        printf("%d ", b);
    } while (i--);
    printf("\n");
}

void
yy(float a)
{
    int sign=!(*(unsigned long long*)&a&((unsigned long long)1<<31));
    int fraction = ((1<<23)-1)&(*(int*)&a);
    int exponent = (255&((*(int*)&a)>>23))-127;

    printf(sign?"positive" " ( 1+":"negative" " ( 1+");
    unsigned int i = 1<<22;
    unsigned int j = 1;
    do {
        char b=(fraction&i)!=0;
        b&&(printf("1/(%d) %c", 1<<j, (fraction&(i-1))?'+':')' ), 0);
    } while (j++, i>>=1);

    printf("*2^%d", exponent);
    printf("\n");
}

void
main()
{
    float x=-3.14;
    float y=999999999;
    printf("%lu\n", sizeof(x));
    xx(&x);
    xx(&y);
    yy(x);
    yy(y);
}

Вот сеанс консоли, в котором я вычисляю реальное значение float, которое существует в аппаратном обеспечении. Я использовал bc для печати суммы терминов, выводимых основной программой. Можно вставить эту сумму в python repl или что-то подобное.

-- .../terra1/stub
@ qemacs f.c
-- .../terra1/stub
@ gcc f.c
-- .../terra1/stub
@ ./a.out
sign:1 exponent:1 0 0 0 0 0 0 fraction:0 1 0 0 1 0 0 0 1 1 1 1 0 1 0 1 1 1 0 0 0 0 1 1
sign:0 exponent:1 0 0 1 1 1 0 fraction:0 1 1 0 1 1 1 0 0 1 1 0 1 0 1 1 0 0 1 0 1 0 0 0
negative ( 1+1/(2) +1/(16) +1/(256) +1/(512) +1/(1024) +1/(2048) +1/(8192) +1/(32768) +1/(65536) +1/(131072) +1/(4194304) +1/(8388608) )*2^1
positive ( 1+1/(2) +1/(4) +1/(16) +1/(32) +1/(64) +1/(512) +1/(1024) +1/(4096) +1/(16384) +1/(32768) +1/(262144) +1/(1048576) )*2^29
-- .../terra1/stub
@ bc
scale=15
( 1+1/(2) +1/(4) +1/(16) +1/(32) +1/(64) +1/(512) +1/(1024) +1/(4096) +1/(16384) +1/(32768) +1/(262144) +1/(1048576) )*2^29
999999999.999999446351872

Вот и все. Фактически значение 999999999

999999999.999999446351872

Вы также можете проверить с помощью bc, что -3.14 также возмущено. Не забудьте установить коэффициент scale в bc.

Отображаемая сумма - это то, что внутри аппаратного обеспечения. Значение, которое вы получаете, вычисляя его, зависит от установленного вами масштаба. Я установил коэффициент scale равным 15. Математически, с бесконечной точностью, кажется, что это 1 000 000 000.

548
задан the Tin Man 27 April 2016 в 19:41
поделиться

5 ответов

Вы можете это сделать полностью, это просто проблема с порядком:

[ unicode(x.strip()) if x is not None else '' for x in row ]

Обратите внимание, что это фактически использует другую конструкцию языка, условное выражение , которое само по себе не является часть синтаксиса понимания , в то время как if после for…in является частью понятий списка и используется для filter элементов из исходной итерации.

Условные выражения могут использоваться во всех ситуациях, когда вы хотите выбрать между двумя значениями выражения на основе некоторого условия. Это делает то же, что и трёхмерный оператор ?:, который существует на других языках . Например:

value = 123
print(value, 'is', 'even' if value % 2 == 0 else 'odd')
841
ответ дан poke 31 August 2018 в 20:35
поделиться

Один из способов:

def change(f):
    if f is None:
        return unicode(f.strip())
    else:
        return ''

row = [change(x) for x in row]

Хотя тогда у вас есть:

row = map(change, row)

Или вы можете использовать встроенный lambda.

35
ответ дан Adam Vandenberg 31 August 2018 в 20:35
поделиться

Вот еще один иллюстративный пример:

>>> print(", ".join(["ha" if i else "Ha" for i in range(3)]) + "!")
Ha, ha, ha!

Он использует тот факт, что if i оценивает False для 0 и True для всех других значений, генерируемых функцией range(). Поэтому понимание списка оценивается следующим образом:

>>> ["ha" if i else "Ha" for i in range(3)]
['Ha', 'ha', 'ha']
30
ответ дан Bengt 31 August 2018 в 20:35
поделиться

Другие решения отлично подходят для одной конструкции if / else. Тем не менее, трехмерные выражения в понимании списка, возможно, трудно читать.

Использование функции облегчает читаемость, но такое решение трудно расширить или адаптировать в рабочем процессе, где отображение является входом. Словарь может облегчить эти проблемы:

row = [None, 'This', 'is', 'a', 'filler', 'test', 'string', None]

d = {None: '', 'filler': 'manipulated'}

res = [d.get(x, x) for x in row]

print(res)

['', 'This', 'is', 'a', 'manipulated', 'test', 'string', '']
0
ответ дан jpp 31 August 2018 в 20:35
поделиться

Конкретная проблема уже решена в предыдущих ответах, поэтому я обращусь к общей идее использования условностей внутри понятий списка.

Вот пример, показывающий, как условные обозначения могут быть записаны внутри понимания списка :

X = [1.5, 2.3, 4.4, 5.4, 'n', 1.5, 5.1, 'a']     # Original list

# Extract non-strings from X to new list
X_non_str = [el for el in X if not isinstance(el, str)]  # When using only 'if', put 'for' in the beginning

# Change all strings in X to 'b', preserve everything else as is
X_str_changed = ['b' if isinstance(el, str) else el for el in X]  # When using 'if' and 'else', put 'for' in the end

Обратите внимание, что в первом понимании списка для X_non_str порядок:

значение для выражения 1 , если expression2

и в последнем понимании списка для X_str_changed порядок:

value1 , если expression1 else значение2 для expression2

Мне всегда трудно помнить, что значение 1 должно быть раньше, если и значение2 должно быть после. Моя голова хочет, чтобы оба были либо до, либо после.

Я предполагаю, что он создан так, потому что он похож на обычный язык, например. «Я хочу остаться внутри, если идет дождь, иначе я хочу выйти на улицу»

3
ответ дан Tim Skov Jacobsen 31 August 2018 в 20:35
поделиться
Другие вопросы по тегам:

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