Por que comparar cadeias 0 (n), mas comparar números 0 (1)?


8

Entendo que, para comparar duas seqüências de caracteres para a igualdade, o intérprete precisa iterar as duas e comparar cada caractere.

Isso tornaria a complexidade do tempo 0(n)onde nestá o comprimento da string mais curta.

No entanto, comparar dois números para igualdade é 0(1).

Por que é que? O intérprete não precisaria percorrer todos os números para verificar a igualdade?


1
O que há para iterar em um número? Um número é apenas o valor: 2por exemplo, não é 3. É isso aí. Da mesma forma 123não é 124. Uma string é uma coleção de caracteres "abc"diferente, "abd"mas você deve verificar cada caractere.
VLAZ 28/10/19

2
Os computadores têm operações intrínsecas que comparam valores de números inteiros rapidamente.
Pointy

5
Se você estiver trabalhando em uma linguagem como Erlang com inteiros infinita de precisão, as comparações numéricas são realmente O (n)
Pointy

1
Também em vez de "através de cada número" provavelmente significa "através de cada dígito"
Pointy

1
@ Pointy: Isso seria O (log (n)), porque o comprimento do número n é proporcional ao log (n).
Nyos

Respostas:


10

Os números nos computadores geralmente são tratados em unidades de tamanho fixo. A intpode ter 32 ou 64 bits em qualquer combinação de idioma e / ou compilador / plataforma, mas nunca terá comprimento variável.

Portanto, você tem um número fixo de bits para comparar ao comparar números. É muito fácil criar um circuito de hardware que compare muitos bits de uma vez (ou seja, como "uma ação").

As strings, por outro lado, têm comprimentos inerentemente variáveis; portanto, você apenas dizendo "string" não diz quantos bits você terá que comparar.

Porém, existem exceções, pois existem números de comprimento variável, geralmente chamados de algo como BigIntegerou BigDecimalque se comportam muito semelhantes à Stringcomparação, pois pode acabar sendo O (n) comparar dois BigDecimalvalores de igualdade (onde n é o comprimento de BigDecimals , nenhum dos valores numéricos).


A presença da tag javascript faz alguma diferença para esta resposta? Em javascript eles têm as ===e ==operadores, onde o ==operador permite a fazer algo como 1 == '1'o que irá avaliar a verdade, mas os docs são muito vagos sobre o que cada um dos operandos são convertidos em diante a comparação é feita. Portanto, neste caso, se eles são convertidos em string, a comparação pode não estar fazendo inteiro comparar, mas sim String de comparação
smac89

@ smac89: JavaScript usa um único tipo numérico, que é um número de ponto flutuante de tamanho fixo, portanto não faz diferença para comparação. Sim, antes da comparação, talvez seja necessário fazer algumas conversões que podem ou não ser possíveis em O (n), mas o IMO não faz parte da comparação.
Joachim Sauer

3
@ smac89 " mas os documentos são muito vagos quanto ao que cada um dos operandos são convertidos antes da comparação ser feita " os documentos são MUITO explícitos em como a comparação entre diferentes tipos deve ser feita.
VLAZ 28/10/19

@VLAZ obrigado pelo link. Parece que a string é convertida em número, o que ainda é, O(n)e esse é o meu ponto de trazer isso à tona, especialmente quando está envolvido em javascript.
smac89

@JoachimSauer JavaScript uses a single numberic typenão está correto. BigInt agora é um tipo
interno de

4

Geralmente, os programas representam números como estruturas de dados de tamanho fixo (valores binários, e é por isso que você pode ver seus tamanhos descritos em bits). Sendo de tamanho fixo, as comparações levariam um tempo constante e seriam O (1), que é um dos benefícios de tal representação. Uma desvantagem seria um limite no intervalo de valores que podem ser representados.

Uma representação alternativa que elimine essa restrição, permitindo um intervalo arbitrariamente grande de números, não seria mais fixada em tamanho e não seria mais O (1) para comparação.


0

Corda

As comparações de cadeia de caracteres geralmente são uma varredura linear dos caracteres, retornando false no primeiro índice em que os caracteres não coincidem.

A complexidade do tempo é O (N) e o tempo real depende de quantos caracteres precisam ser verificados antes que as diferenças apareçam estatisticamente. Não há uma resposta simples, mas a resposta é óbvia ;-)

Números

se dois números inteiros são iguais, é impossível saber sem comparar todos os seus bits. Portanto, em caso de igualdade, o tempo necessário é proporcional ao número de bits (que é proporcional ao log (abs (N)) se N for um dos comparandos).

Se eles não são iguais, existem muitos casos, todos relevantes para a implementação interna. Ints longos são armazenados como um vetor de "dígitos" em uma base de potência de 2. Se os vetores não tiverem o mesmo comprimento, as entradas não serão iguais, e isso leva tempo constante.

Mas se tiverem o mesmo comprimento, os "dígitos" deverão ser comparados até encontrar o primeiro (se houver) par incompatível. Isso leva um tempo proporcional ao número de dígitos que precisam ser comparados.


Os dígitos não são comparados. Os bits são comparados. E os bits são comparados como um grupo atômico. Nenhum computador compara o bit 1, depois o bit 2, o bit 3 e o bit 4. Dependendo da instrução específica usada e dos recursos do processador, eles comparam 8 bits ou 16 bits ou 32 bits ou 64 bits, etc. , como uma única operação. Não comparação em nível de dígito ou equivalente, está nos limites de byte / palavra.
Ghedipunk

0

Em geral, usamos a notação big-O somente quando n pode subir para valores obscenamente grandes, porque a notação big-O descreve como o tempo de execução aumenta à medida que a entrada aumenta. Por exemplo, ao classificar uma lista, a maioria dos melhores algoritmos é classificada O(n log n)- o que significa, e somente significa, que quando a lista é longa o suficiente, o tempo que leva para classificá-la é proporcional an log n . Quando a lista não é longa o suficiente, outros fatores (por exemplo, a qualquer momento que seu algoritmo leve para alocar espaço extra) tornam-se significativos e podem potencialmente levar o tempo de execução.

Com seqüências de JavaScript, npode realmente ficar arbitrariamente grande *, por isso dizemos que a comparação leva O(n)tempo. Porém, com números JavaScript (que são números de ponto flutuante de precisão dupla IEEE 754 ), ntem um limite máximo de 64-1 para um bit de sinal, 11 para um expoente e 53 para dígitos significativos **. Por isso, sabemos exatamente quanto tempo levará para que uma comparação de números ocorra, e os melhores sistemas que temos para comparar números desse tamanho exato funcionam mais ou menos da mesma forma, independentemente de quantos desses 64 dígitos cada número realmente Portanto, a comparação desses números no JavaScript é considerada O(1).


* Tecnicamente, há um limite superior porque a RAM pode acabar. No entanto, o idioma não especifica um tamanho máximo para seqüências de caracteres, e oO(n) parte da comparação de cadeias domina o tempo de execução muito antes disso.

** A propósito, isso significa que os números no JavaScript não podem aumentar infinitamente. Depois de um certo ponto, eles começam a jogar fora dígitos menores (por exemplo, números acima de 2 ^ 53 só podem ser pares e números acima de 2 ^ 54 só podem ser divisíveis por 4) e, quando o número fica grande o suficiente, ele arredonda para cima ao infinito. Por outro lado, se você dividir um número repetidamente para torná-lo infinitesimalmente pequeno, ele acabará arredondando para zero.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.