Преобразование строки в число и наоборот сложность
какова будет сложность преобразования строки в эквивалентное число или наоборот? Меняется ли он в зависимости от языка программирования?
на первый взгляд, нужно пересечь всю строку, чтобы преобразовать ее в число, так что это O (n), или используется какая-то типизация?
это сомнение возникло, когда я писал рутину, чтобы проверить, является ли данное число палиндромом или нет. Один подход будет держать деления числа на база (здесь 10), накапливайте цифры и складывайте их вместе в конце. Пример: 309/10=rem(9), 30/10=rem(0), 3/10=rem (3). мы получаем 903.
другой подход, который я принял, состоял в том, чтобы преобразовать это число в строку, и поскольку строки имеют множество функций-членов для разделения, обратного и т. д. код был намного короче и чище, но это лучший способ, чтобы сделать это?
5 ответов
числовые строки-это числа, отформатированные в позиционной нотации, поэтому значение каждой цифры, умноженное на мощность базы, необходимо учитывать, чтобы преобразовать число в двоичный формат.
Так что да, это операция O(N), потому что время выполнения увеличивается линейно по мере добавления большего количества цифр. Однако на практике N может быть ограничено любыми числовыми типами данных, которые поддерживает язык (например, int32_t, int64_t). Но если произвольные типы чисел точности используется (который некоторые языки, такие как Python, используют по умолчанию), то нет ограничений на количество цифр (кроме доступной памяти, очевидно).
преобразовать в число, вы всегда должны прочитать все цифры. Так что это по крайней мере O(n)
.
Теперь делаем что-то вроде (псевдокода)
a = 0
foreach digit in string
do
a = 10 * a + digit
end
Is O(n)
. Таким образом, сложность O(n)
Если вы преобразуете число N в строку. Он принимает O (log (N)) с основанием 10. (Если разделить на 10 и сохранить остаток) Если вы конвертируете строку с длиной N, то она принимает O(N). (Если вы используете алгоритм, который продолжает добавлять к вашему номеру 10^(N) * цифра(N))
Если вы используете функции, которые не являются вашими (скажем, для строки), вы можете ожидать, что они будут медленнее.
Я достаточно уверен, что работа с чистыми числовыми операторами (в C++ и c# я думаю, что это будет оператор модуля"%") будет более эффективной, если она будет правильно закодирована, потому что на некотором уровне вам нужно проверить наличие аналогичных функций (конец совпадает с началом), и выполнение преобразования между строкой и числом может только добавить к сложности операции, если вы можете сделать то же самое без выполнения этого преобразования.
тем не менее, я бы не беспокоился о влияние на производительность преобразования чисел и строк, поскольку оно, вероятно, незначительно по сравнению с влиянием на производительность большинства других областей программы. Числовые типы ограничены 64 битами, что ставит относительно низкий предел количеству цифр, которые вы можете запланировать для анализа в любом случае, если вы не реализуете/не используете пользовательские типы больших чисел.
вам не нужно беспокоиться о сложности O(n), где n-величина числа. Было бы больше похоже O (n), где n-количество цифр (с низкой крышкой, о которой я упоминал) или (как упоминалось в другом ответе) O(log(n)), если n-величина числа. Относительно незначительное влияние на производительность.
теперь, если, как вы предполагаете, у вас нет ограничений на N (что невозможно, потому что с 2 ГБ ОЗУ вы можете хранить только числа с 2 миллиардами цифр), тогда нам, возможно, придется больше думать о производительности выполнения математических операторов. Рассмотрим работу оператор " % " и " / " для этого типа большого числа. Но затем осознайте, что для преобразования числа в строку он в основном использует те же операторы. Еще раз, вы не можете превзойти обработку его как числа напрямую, если вы сделаете это правильно.
C# и C / C++ не имеют никакой специальной информации в строках, которая представляет (возможное) числовое значение. Поэтому при преобразовании им необходимо проанализировать строковую цифру по цифре.
однако количество цифр ограничено, поэтому у нас есть только O(1): время преобразования ограничено (обычно преобразованием самого большого числа). Для 32-разрядного int преобразование должно учитывать максимум 10 десятичных цифр (и, возможно, знак).
преобразование из строка на самом деле O(1), потому что при ее разборе достаточно рассмотреть только ограниченное количество символов (10+1 в случае 32-битного int).
строго говоря, мы не можем использовать O
-обозначение для случая преобразования int в строку, так как максимальное значение int ограничено. В любом случае, время, необходимое для преобразования (в обоих направлениях) ограничено константой.
как предполагает @Charles, другие языки (Python) фактически могут использовать произвольную точность числа. Для разбора таких чисел время O(number of digits)
, который O(string length)
и O(log(number))
для преобразования, соответственно. С числами произвольной точности это невозможно сделать быстрее, так как для обоих преобразований необходимо учитывать каждую цифру. Для преобразования в / из чисел с ограниченной точностью, то же самое O(1)
аргументация применима. Однако я сам не профилировал синтаксический анализ в Python, поэтому, возможно, там используется менее эффективный алгоритм.
EDIT: после @Steve предложение, я проверил, что синтаксический анализ в C / C++ и C# пропускает начальные пробелы, поэтому время для преобразования string->int на самом деле O(input length)
. Если известно, что строка обрезается, преобразование снова O(1)
.