как преобразовать число, чтобы иметь один и тот же питон? [Дубликат]

Чтобы отследить наиболее важные моменты: если вы используете это на одной платформе компилятора / HW в качестве программного обеспечения только для конструирования, то утверждение не будет проблемой. Если вы используете код или данные на нескольких платформах или должны соответствовать макетам аппаратного бита, тогда это IS проблема. И много профессионального программного обеспечения является кросс-платформенным, поэтому он должен заботиться.

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

Конкретный пример:

int16_t s = 4096; // подписанное 16-битное число ...

Предположим, что моя программа поставляется с некоторыми данными на диске, который я хочу прочитать. Скажем, я хочу загрузить его как 4096 в этом случае ...

fread ((void *) & amp; s, 2, fp); // читаю его с диска как двоичный ...

Здесь я прочитал его как 16-битное значение, а не как явные байты. Это означает, что если моя система соответствует контенту, хранящемуся на диске, я получаю 4096, а если это не так, я получаю 16 !!!!!

. Таким образом, наиболее частое использование endianness - номера, а затем выполните bswap, если вы не соответствуете. Раньше мы хранили данные на диске как большие, потому что Intel был странным человеком и предоставлял высокоскоростные инструкции для обмена байтами. В настоящее время Intel настолько распространена, что часто делает Little Endian по умолчанию и свопит, когда на большой системе endian.

Более медленный, но нейтральный подход, основанный на endian, состоит в том, чтобы делать ВСЕ I / O по байтам, то есть:

uint_8 ubyte; int_8 sbyte; int16_t s; // читаем s в нейтральном нейтральном направлении

// Давайте выберем маленький конец в качестве нашего выбранного порядка байтов:

fread ((void *) & amp; ubyte, 1, fp); // Только чтение 1 байт за время fread ((void *) & amp; sbyte, 1, fp); // Только чтение 1 байт за раз

// Реконструкция s

s = ubyte | (sByte & lt; 8);

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

Я использовал пример хранимых данных, используемых программой. Другое основное приложение - записать аппаратные регистры, где эти регистры имеют абсолютный порядок. Одно ОЧЕНЬ ОБЩЕЕ место, которое появляется, это графика. Избегайте верности, и ваши каналы красного и синего цвета меняются на противоположные! Опять же, проблема заключается в переносимости - вы можете просто адаптироваться к данной аппаратной платформе и графической карте, но если вы хотите, чтобы ваш одинаковый код работал на разных машинах, вы должны проверить.

Вот классический тест :

typedef union {uint_16 s; uint_8 b [2]; } EndianTest_t;

EndianTest_t test = 4096;

if (test.b [0] == 12) printf («Big Endian Detected! \n»);

Обратите внимание, что проблемы с битовыми полями существуют, но они ортогональны проблемам с контентом.

34
задан skornos 10 March 2012 в 16:27
поделиться

16 ответов

Я обнаружил, что делаю что-то подобное, нужно преобразовать адреса с порядковыми номерами («Третий St») в формат, который может постигнуть геокодер («Третий St»). Хотя это не очень элегантно, одним быстрым и грязным решением является использование inflect.py для создания словаря для перевода.

Функция inflect.py имеет функцию number_to_words(), которая превратит число (например, 2) в его текстовую форму (например, 'two'). Кроме того, существует функция ordinal(), которая будет принимать любое число (цифра или форма слова) и превращать его в его порядковую форму (например, 4 -> fourth, six -> sixth). Ни один из них сам по себе не выполняет то, что вы ищете, но вместе вы можете использовать их для создания словаря для перевода любого предоставленного порядкового номера-слова (в пределах разумного диапазона) в соответствующий порядковый номер. Взгляните:

>>> import inflect
>>> p = inflect.engine()
>>> word_to_number_mapping = {}
>>>
>>> for i in range(1, 100):
...     word_form = p.number_to_words(i)  # 1 -> 'one'
...     ordinal_word = p.ordinal(word_form)  # 'one' -> 'first'
...     ordinal_number = p.ordinal(i)  # 1 -> '1st'
...     word_to_number_mapping[ordinal_word] = ordinal_number  # 'first': '1st'
...
>>> print word_to_number_mapping['sixth']
6th
>>> print word_to_number_mapping['eleventh']
11th
>>> print word_to_number_mapping['forty-third']
43rd

Если вы готовы посвятить некоторое время, возможно, будет возможно изучить внутреннюю работу inflect.py в обеих этих функциях и создать свой собственный код, чтобы сделать это динамически (Я не пытался это сделать).

6
ответ дан alukach 17 August 2018 в 11:58
поделиться

Это может обрабатывать любое число длины, исключения для ... # 11 ... ... 13 и отрицательные целые числа.

def ith(i):return(('th'*(10<(abs(i)%100)<14))+['st','nd','rd',*['th']*7][(abs(i)-1)%10])[0:2]

Я предлагаю использовать iith () в качестве имени, чтобы избежать переопределения встроенный ord ().

# test routine
for i in range(-200,200):
    print(i,ith(i))

Примечание: проверено с помощью Python 3.6; Функция abs () была доступна без явного включения математического модуля.

1
ответ дан Amp Balfour 17 August 2018 в 11:58
поделиться

Код Гарета, выраженный с использованием современного .format ()

ordinal = lambda n: "{}{}".format(n,"tsnrhtdd"[(n/10%10!=1)*(n%10<4)*n%10::4])
0
ответ дан best_practice_guy 17 August 2018 в 11:58
поделиться

Принятый ответ предыдущего вопроса имеет алгоритм для половины этого: он превращает "first" в 1. Чтобы перейти оттуда к "1st", сделайте что-то вроде:

suffixes = ["th", "st", "nd", "rd", ] + ["th"] * 16
suffixed_num = str(num) + suffixes[num % 100]

Это работает только для чисел 0-19.

7
ответ дан Community 17 August 2018 в 11:58
поделиться
  • 1
    поэтому, если я прав, тогда мне нужно написать все значения в dict, например {'first': '1', 'second': '2', 'third': '3', '4th': '4', ' ...} так или иначе? – skornos 10 March 2012 в 17:58
  • 2
    @skornos да. В общем, нет никакого способа сделать это, не имея такого дикта. Но с достаточным количеством Googling вы, вероятно, найдете, что кто-то уже выполнил для вас тяжелый трудный бит. В противном случае, если вы действительно сделаете это самостоятельно, вы можете избежать списка suffixes, настроив свой dict как {'first': '1st'} и т. Д. – lvc 11 March 2012 в 10:13
  • 3
    Черт возьми, я люблю Питона. – Robert Grant 1 September 2015 в 13:06
  • 4
    Это, кажется, больше не работает в python3.4, например. ординал (13) = '13rd'. Я не знаю, почему. str (n) + {1: 'st', 2: 'nd', 3: 'rd'}. get (4, если 10 & lt; = n% 100 & lt; 20 else n% 10, "th") работает , – Brett DiDonato 30 January 2016 в 22:50
  • 5
    @BrettDiDonato n/10 требует / быть целочисленным делением, которое изменилось между Python 2 и 3 – Sp3000 16 February 2016 в 04:29
  • 6
    милый, но c'mon, это просто уродливый – Wells 3 June 2016 в 00:21
  • 7
    вы можете использовать // для целочисленного деления в python3: ordinal = lambda n: "% d% s" % (n, "tsnrhtdd" [(n // 10% 10! = 1) * (n% 10 и 4) * n% 10 :: 4]) – Xerion 19 January 2017 в 20:53

Я думаю, что у меня однострочное решение.

str(n) + list(['th','st','nd','rd'] + ['th'] * 6) [int(str(n)[-1]) % 10]

Это работает, выбирая суффикс из списка, используя модуль десять последней цифры. Таким образом, он работает для всех целых чисел. Квадратные скобки для победы!

(Спасибо пользователю lvc за напоминание, что мы можем размножать списки.)

EDIT: Я только что понял, что выше не работает, если число заканчивается на 11, 12 или 13. Пересмотренный код:

str(n) + (list(['th','st','nd','rd'] + ['th'] * 6) [(int(str(n)[-1])) % 10] if not int(str(n)[-2:]) % 100 in range(11, 14) else 'th')
0
ответ дан CosmicStresshead 17 August 2018 в 11:58
поделиться

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

def ordinal( n ):

    suffix = ['th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th']

    if n < 0:
        n *= -1

    n = int(n)

    if n % 100 in (11,12,13):
        s = 'th'
    else:
        s = suffix[n % 10]

    return str(n) + s
1
ответ дан Dario Z. 17 August 2018 в 11:58
поделиться
  • 1
    Это некромант в том, что тема была мертва, но ... это хорошее некромантирование. Никакой милый код, очень разборчивый и легко понять. Ницца! – chris.leonard 7 June 2017 в 07:22

Как насчет этого:

suf = lambda n: "%d%s"%(n,{1:"st",2:"nd",3:"rd"}.get(n if n<20 else n%10,"th"))
print [suf(n) for n in xrange(1,32)]

['1st', '2nd', '3rd', '4th', '5th', '6th', '7th', '8th', '9th', '10th',
 '11th', '12th', '13th', '14th', '15th', '16th', '17th', '18th', '19th',
 '20th', '21st', '22nd', '23rd', '24th', '25th', '26th', '27th', '28th',
 '29th', '30th', '31st']
5
ответ дан evandrix 17 August 2018 в 11:58
поделиться
  • 1
    Мне нравится этот, более читаемый. Но работает ли оно на n & gt; 100? – Xerion 19 January 2017 в 21:00

Если вы не хотите втягивать дополнительную зависимость от внешней библиотеки (как , предложенной luckydonald ), но также не хотите, чтобы будущий сопровождающий кода преследовал вас и убивал вы (потому что вы использовали код для гольфа в производстве), то вот короткий вариант, но поддерживаемый:

def make_ordinal(n):
    '''
    Convert an integer into its ordinal representation::

        make_ordinal(0)   => '0th'
        make_ordinal(3)   => '3rd'
        make_ordinal(122) => '122nd'
        make_ordinal(213) => '213th'
    '''
    n = int(n)
    suffix = ['th', 'st', 'nd', 'rd', 'th'][min(n % 10, 4)]
    if 11 <= (n % 100) <= 13:
        suffix = 'th'
    return str(n) + suffix
1
ответ дан Florian Brucker 17 August 2018 в 11:58
поделиться

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

Он работает, определяя, выше или ниже 20, если число ниже 20, оно превратит int 1 в строку 1, 2, 2; 3, 3; а остальные будут добавлены к ней.

Для чисел более 20 он будет принимать последние и секунды до последних цифр, которые я назвал десятками и единицами соответственно, и проверим их, чтобы увидеть, что добавить к числу.

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

def o(numb):
    if numb < 20: #determining suffix for < 20
        if numb == 1: 
            suffix = 'st'
        elif numb == 2:
            suffix = 'nd'
        elif numb == 3:
            suffix = 'rd'
        else:
            suffix = 'th'  
    else:   #determining suffix for > 20
        tens = str(numb)
        tens = tens[-2]
        unit = str(numb)
        unit = unit[-1]
        if tens == "1":
           suffix = "th"
        else:
            if unit == "1": 
                suffix = 'st'
            elif unit == "2":
                suffix = 'nd'
            elif unit == "3":
                suffix = 'rd'
            else:
                suffix = 'th'
    return str(numb)+ suffix

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

Дайте мне знать, что вы думаете: D

5
ответ дан Houngan 17 August 2018 в 11:58
поделиться

Это альтернативные варианты использования пакета num2words.

>>> from num2words import num2words
>>> num2words(42, to='ordinal_num')
    '42nd'
1
ответ дан Klahnen 17 August 2018 в 11:58
поделиться

Другим решением является библиотека num2words ( pip | github ). Он особенно предлагает разные языки, поэтому локализация / интернационализация (aka. L10n / i18n) не вызывает затруднений.

Использование легко после установки с помощью pip install num2words:

from num2words import num2words
# english is default
num2words(4458, to="ordinal_num")
'4458rd'

# examples for other languages
num2words(4458, lang="en", to="ordinal_num")
'4458rd'

num2words(4458, lang="es", to="ordinal_num")
'4458º'

num2words(4458, lang="de", to="ordinal_num")
'4458.'

num2words(4458, lang="id", to="ordinal_num")
'ke-4458'

Бонус:

num2words(4458, lang="en", to="ordinal")
'four thousand, four hundred and fifty-eighth'
2
ответ дан luckydonald 17 August 2018 в 11:58
поделиться

Если вы используете django, вы можете сделать:

from django.contrib.humanize.templatetags.humanize import ordinal
var = ordinal(number)

(или использовать порядковый номер в шаблоне django в качестве фильтра шаблона, которым он был предназначен, хотя его так же называют из кода python )

Если вы не используете django, вы можете украсть их реализацию , которая очень аккуратная.

1
ответ дан Monika Sulik 17 August 2018 в 11:58
поделиться

Вот более сложное решение, которое я только что написал, что учитывает составленные ординалы. Поэтому он работает от first до nine hundred and ninety ninth. Мне нужно было преобразовать строковые названия улиц в число ординалов:

import re
from collections import OrderedDict

ONETHS = {
    'first': '1ST', 'second': '2ND', 'third': '3RD', 'fourth': '4TH', 'fifth': '5TH', 'sixth': '6TH', 'seventh': '7TH',
    'eighth': '8TH', 'ninth': '9TH'
}

TEENTHS = {
    'tenth': '10TH', 'eleventh': '11TH', 'twelfth': '12TH', 'thirteenth': '13TH',
    'fourteenth': '14TH', 'fifteenth': '15TH', 'sixteenth': '16TH', 'seventeenth': '17TH', 'eighteenth': '18TH',
    'nineteenth': '19TH'
}

TENTHS = {
    'twentieth': '20TH', 'thirtieth': '30TH', 'fortieth': '40TH', 'fiftieth': '50TH', 'sixtieth': '60TH',
    'seventieth': '70TH', 'eightieth': '80TH', 'ninetieth': '90TH',
}

HUNDREDTH = {'hundredth': '100TH'}  # HUNDREDTH not s

ONES = {'one': '1', 'two': '2', 'three': '3', 'four': '4', 'five': '5', 'six': '6', 'seven': '7', 'eight': '8',
        'nine': '9'}

TENS = {'twenty': '20', 'thirty': '30', 'forty': '40', 'fifty': '50', 'sixty': '60', 'seventy': '70', 'eighty': '80',
        'ninety': '90'}

HUNDRED = {'hundred': '100'}

# Used below for ALL_ORDINALS
ALL_THS = {}
ALL_THS.update(ONETHS)
ALL_THS.update(TEENTHS)
ALL_THS.update(TENTHS)
ALL_THS.update(HUNDREDTH)

ALL_ORDINALS = OrderedDict()
ALL_ORDINALS.update(ALL_THS)
ALL_ORDINALS.update(TENS)
ALL_ORDINALS.update(HUNDRED)
ALL_ORDINALS.update(ONES)


def split_ordinal_word(word):
    ordinals = []
    if not word:
        return ordinals 

    for key, value in ALL_ORDINALS.items():
        if word.startswith(key):
            ordinals.append(key)
            ordinals += split_ordinal_word(word[len(key):])
            break
    return ordinals

def get_ordinals(s):
    ordinals, start, end = [], [], []
    s = s.strip().replace('-', ' ').replace('and', '').lower()
    s = re.sub(' +',' ', s)  # Replace multiple spaces with a single space
    s = s.split(' ')

    for word in s:
        found_ordinals = split_ordinal_word(word)
        if found_ordinals:
            ordinals += found_ordinals
        else:  # else if word, for covering blanks
            if ordinals:  # Already have some ordinals
                end.append(word)
            else:
                start.append(word)
    return start, ordinals, end


def detect_ordinal_pattern(ordinals):
    ordinal_length = len(ordinals)
    ordinal_string = '' # ' '.join(ordinals)
    if ordinal_length == 1:
        ordinal_string = ALL_ORDINALS[ordinals[0]]
    elif ordinal_length == 2:
        if ordinals[0] in ONES.keys() and ordinals[1] in HUNDREDTH.keys():
            ordinal_string = ONES[ordinals[0]] + '00TH'
        elif ordinals[0] in HUNDRED.keys() and ordinals[1] in ONETHS.keys():
            ordinal_string = HUNDRED[ordinals[0]][:-1] + ONETHS[ordinals[1]]
        elif ordinals[0] in TENS.keys() and ordinals[1] in ONETHS.keys():
            ordinal_string = TENS[ordinals[0]][0] + ONETHS[ordinals[1]]
    elif ordinal_length == 3:
        if ordinals[0] in HUNDRED.keys() and ordinals[1] in TENS.keys() and ordinals[2] in ONETHS.keys():
            ordinal_string = HUNDRED[ordinals[0]][0] + TENS[ordinals[1]][0] + ONETHS[ordinals[2]]
        elif ordinals[0] in ONES.keys() and ordinals[1] in HUNDRED.keys() and ordinals[2] in ALL_THS.keys():
            ordinal_string =  ONES[ordinals[0]] + ALL_THS[ordinals[2]]
    elif ordinal_length == 4:
        if ordinals[0] in ONES.keys() and ordinals[1] in HUNDRED.keys() and ordinals[2] in TENS.keys() and \
           ordinals[3] in ONETHS.keys():
                ordinal_string = ONES[ordinals[0]] + TENS[ordinals[2]][0] + ONETHS[ordinals[3]]

    return ordinal_string

И вот несколько примеров использования:

# s = '32 one   hundred and forty-third st toronto, on'
#s = '32 forty-third st toronto, on'
#s = '32 one-hundredth st toronto, on'
#s = '32 hundred and third st toronto, on'
#s = '32 hundred and thirty first st toronto, on'
# s = '32 nine hundred and twenty third st toronto, on'
#s = '32 nine hundred and ninety ninth st toronto, on'
s = '32 sixty sixth toronto, on'

st, ords, en = get_ordinals(s)
print st, detect_ordinal_pattern(ords), en
0
ответ дан radtek 17 August 2018 в 11:58
поделиться

Если вы не хотите импортировать внешний модуль и предпочитаете однострочное решение, то, вероятно, (немного) более читабельным, чем принятый ответ:

def suffix(i):
    return {1:"st", 2:"nd", 3:"rd"}.get(i%10*(i%100 not in [11,12,13]), "th"))

Он использует словарь .get, как предложено https://codereview.stackexchange.com/a/41300/90593 и https://stackoverflow.com/a/36977549/5069869 .

Я использовал умножение с булевым для обработки особых случаев (11,12,13) ​​без необходимости запуска if-блока. Если условие (i%100 not in [11,12,13]) оценивается как False, все число равно 0, и мы получаем случай по умолчанию «th».

1
ответ дан TheEspinosa 17 August 2018 в 11:58
поделиться
0
ответ дан best_practice_guy 6 September 2018 в 08:51
поделиться
1
ответ дан Roy G 29 October 2018 в 15:29
поделиться
Другие вопросы по тегам:

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