Um computador tentará dividir por zero?


59

Todos nós sabemos que 0/0é Undefinede retorna um erro se eu o colocasse em uma calculadora e se eu criasse um programa (pelo menos em C) o sistema operacional o encerraria quando tento dividir por zero.

Mas o que eu queria saber é se o computador tenta dividir por zero , ou apenas possui "proteção interna", de modo que, quando "vê" 0/0, retorna um erro antes mesmo de tentar calculá-lo?


10
0/0 é indefinido, qualquer outro número / 0 é um tipo diferente de erro, você parece confundir os dois
edc65

7
Qualquer número dividido por 0 é indefinido, matematicamente falando.
ManoDestra 26/02

12
@jwg: "se tivesse um valor, seria 1" - não necessariamente; existem ramos inteiros da matemática dedicados ao que o valor pode ser em circunstâncias diferentes :)
psmears

11
Para esclarecer a terminologia aqui, 0/0 é chamado de forma indeterminada, enquanto x / 0 para x diferente de zero é indefinido . Um cálculo que termina com 0/0 geralmente pode ser calculado de uma maneira diferente para fornecer uma resposta real, enquanto x / 0 é essencialmente sem sentido.
Era

9
@ jwg você pode estar interessado na regra de l'hopital então. Definitivamente, existem casos em que 0/0 não implica um valor de 1.
d0nut

Respostas:


74

A CPU foi incorporada na detecção. A maioria das arquiteturas de conjunto de instruções especifica que a CPU interceptará um manipulador de exceção para a divisão de números inteiros por zero (não acho que se importe se o dividendo for zero).

É possível que a verificação de um divisor zero ocorra paralelamente no hardware, juntamente com a tentativa de fazer a divisão; no entanto, a detecção da condição ofensiva efetivamente cancela a divisão e intercepta, portanto, não podemos realmente dizer se alguma parte disso, tentou a divisão ou não.

(O hardware geralmente funciona dessa maneira, fazendo várias coisas em paralelo e depois escolhendo o resultado apropriado, porque todas as operações podem começar imediatamente, em vez de serializar a escolha da operação apropriada.)

O mesmo mecanismo de interceptação para exceção também será usado quando a detecção de estouro estiver ativada, o que você solicita geralmente usando instruções add / sub / mul diferentes (ou um sinalizador nessas instruções).

A divisão de ponto flutuante também tem detecção embutida para dividir por zero, mas retorna um valor diferente ( IEEE 754 especifica NaN ) em vez de interceptar um manipulador de exceção.


Hipoteticamente, se a CPU omitir qualquer detecção por tentativa de dividir por zero, os problemas podem incluir:

  • travar a CPU (por exemplo, em um loop inf.) - isso pode acontecer se a CPU usar um algoritmo para dividir que para quando o numerador for menor que o divisor (em valor absoluto). Um travamento como esse contaria praticamente como travar a CPU.
  • uma resposta de lixo (possivelmente previsível), se a CPU usar um contador para terminar a divisão no número máximo possível de etapas de divisão (por exemplo, 31 ou 32 em uma máquina de 32 bits).

51
@ Ankush Uma "falha no sistema" não é realmente algo que acontece no nível da CPU. O comportamento mais provável de uma CPU que não interceptou a divisão por zero seria que ele simplesmente faz a operação de divisão, produz algum resultado sem sentido e continua. Assim como quando você adiciona dois números inteiros que transbordam.
Ixrec 26/02

6
Para ponto flutuante, a escolha entre "NaN" e "armadilha" geralmente é configurável ao se disparar sinalizadores na FPU.
Vatine 26/02/16

10
@ Ankush No caso do que o lxrec disse não estar claro: no que diz respeito à CPU, não existe uma falha.
user253751

7
@Ankush Poucas situações causam uma "falha no sistema" no nível da CPU. Nesses casos, estamos falando de coisas como desligamento da proteção térmica (proteção contra superaquecimento), falhas triplas e situações semelhantes. Quase todas as falhas que você encontrará em uso comum, incluindo códigos de operação inválidos , são tratadas por interceptar e recuperar alguma maneira, ou simplesmente ignorando o erro e continuando a execução em um estado potencialmente impuro, talvez tendo definido algum sinalizador de erro.
a CVn 26/02

8
Se você não dividisse a divisão por zero, o resultado seria, na linguagem da programação, "Comportamento indefinido". Isso significa que o computador pode fazer qualquer coisa. Como Bergi menciona, pode entrar em um loop de buggy e travar. Ele pode simplesmente emitir algumas séries não especificadas de bits que aconteceram com a implementação da lógica de divisão (lembre-se, um computador não "se divide" no sentido matemático. Faz uma operação em dois números, o que é próximo o suficiente da divisão que normalmente chamamos de "divisão" (veja também arredondamento de ponto flutuante).
Cort Ammon

34

Depende do idioma, do compilador, se você está usando números inteiros ou de ponto flutuante, e assim por diante.

Para número de ponto flutuante, a maioria das implementações usa o padrão IEEE 754 , onde a divisão por 0 é bem definida. 0/0 fornece um resultado bem definido de NaN (não um número), e x / 0 para x ≠ 0 fornece + Infinity ou -Infinity, dependendo do sinal de x.

Em linguagens como C, C ++ etc., a divisão por zero invoca um comportamento indefinido. Portanto, de acordo com a definição da linguagem, tudo pode acontecer. Especialmente coisas que você não quer que aconteça. Como tudo funcionando perfeitamente quando você escreve o código e destrói os dados quando o cliente o usa. Portanto, do ponto de vista do idioma, não faça isso . Alguns idiomas garantem que seu aplicativo falhe; cabe a eles como isso é implementado. Para esses idiomas, a divisão por zero falhará.

Muitos processadores possuem algum tipo de instrução de "divisão" integrada, que se comportará de maneira diferente dependendo do processador. Nos processadores Intel de 32 bits e 64 bits, as instruções "dividir" travam o aplicativo quando você tenta dividir por zero. Outros processadores podem se comportar de maneira diferente.

Se um compilador detectar que uma divisão por zero ocorrerá quando você executar algum código, e o compilador for bom para seus usuários, provavelmente fornecerá um aviso e gerará uma instrução interna de "divisão" para que o comportamento seja o mesmo.


22
"Nos processadores Intel de 32 bits e 64 bits, as instruções" dividir "travam seu aplicativo quando você tenta dividir por zero." Citação necessária. As CPUs não têm idéia sobre os aplicativos, executam instruções e (se incluirmos o MMU) impõem limites de acesso à memória (a menos que no anel 0 ou equivalente em arquiteturas que não sejam Intel-x86). Que a instrução faz parte do Aplicativo A em vez do Aplicativo B ou do Componente do Sistema Operacional C é irrelevante para a CPU; se a instrução pode ser a Instrução X ou usar o Endereço de Memória Y é relevante.
a CVn 26/02

1
Para adicionar ao comentário do MichaelKjörling: O sistema operacional tem maneiras de não aplicar a aplicação disso (e de outros tipos de erros). No mundo do Windows, é o EXCEPTION_INT_DIVIDE_BY_ZEROvalor no EXCEPTION_RECORDqual será tratado pelo (esperançosamente) manipulador de manipulação de exceção estruturada instalado
user45891

1
Às vezes, eles fazem outras coisas além de garantir que seu aplicativo falhe. Por exemplo, muitos idiomas / plataformas garantem que lançarão uma exceção na divisão por zero. Você pode capturar e manipular a exceção sem travar.
reirab

2
Você pode excluir o "pode" em "Outros processadores podem se comportar de maneira diferente": Na plataforma PowerPC, a divisão apenas produz um resultado zero na divisão por zero. O que é muito mais útil do que o comportamento de pânico da plataforma X86.
cmaster

13

Parece que você está se perguntando o que aconteceria se alguém fizesse uma CPU que não verifica explicitamente zero antes de dividir. O que aconteceria depende inteiramente da implementação da divisão. Sem entrar em detalhes, um tipo de implementação produziria um resultado com todos os bits definidos, por exemplo, 65535 em uma CPU de 16 bits. Outro pode desligar.


1

Mas o que eu queria saber é se o computador tenta dividir por zero, ou apenas possui "proteção interna", de modo que, quando "vê" 0/0, retorna um erro antes mesmo de tentar calculá-lo?

Como x/0não faz sentido, ponto final, os computadores devem sempre verificar a divisão por zero. Há um problema aqui: os programadores querem calcular (a+b)/csem ter que se preocupar em verificar se esse cálculo ainda faz sentido. A resposta secreta à divisão por zero pela CPU + tipo de número + sistema operacional + idioma é fazer algo bastante drástico (por exemplo, travar o programa) ou fazer algo excessivamente benigno (por exemplo, criar um valor que não prejudique sentido como o ponto flutuante IEEE NaN, um número que é "Não é um número").

Em um ambiente comum, espera-se (a+b)/cque um programador saiba se faz sentido. Nesse contexto, não há razão para verificar a divisão por zero. Se a divisão por zero ocorrer, e se a resposta da linguagem de máquina + linguagem de implementação + tipo de dados + sistema operacional a isso for travar o programa, tudo bem. Se a resposta for criar um valor que possa eventualmente poluir todos os números do programa, tudo bem também.

Nem "algo drástico" ou "excessivamente benigno" é a coisa certa a se fazer no mundo da computação de alta confiabilidade. Essas respostas padrão podem matar um paciente, derrubar um avião ou fazer uma bomba explodir no lugar errado. Em um ambiente de alta confiabilidade, um programador que escreve (a+b)/cserá morto durante a revisão de código ou, nos tempos modernos, talvez morto automaticamente por uma ferramenta que verifica construções de verboten. Nesse ambiente, esse programador deveria ter escrito algo como div(add(a,b),c)(e possivelmente alguma verificação do status do erro). Sob o capô, as div(e também as add) funções / macros protegem contra a divisão por zero (ou transbordamento no caso de add). O que essa proteção implica é muito específico da implementação.


Só porque o NaN não obedece à aritmética que você aprendeu na escola não significa que não faz sentido. Ele obedece diferente aritmética
Caleth

-2

Já sabemos disso x/0e 0/0não temos respostas bem definidas. O que acontece se você tentar calcular de 0/0qualquer maneira?

Em um sistema moderno, o cálculo é passado para a MPU na CPU e é sinalizado como uma operação ilegal, retornando NaN.

Em um sistema muito mais antigo, como os computadores domésticos dos anos 80 que não tinham divisão no chip, o cálculo era feito por qualquer software que estivesse sendo executado. Existem algumas opções possíveis:

  • Subtraia cópias cada vez menores do divisor até o valor chegar a zero e acompanhe quais cópias de tamanho foram subtraídas
    • Se verificar zero antes da primeira subtração, sairá rapidamente e o resultado será 0
    • Se considerar que deve poder subtrair pelo menos uma vez, o resultado será 1
  • Calcule os logaritmos de ambos os números, subtraia-os e aumente e à potência do resultado. Um método muito ineficiente comparado ao método de subtração acima, mas matematicamente válido
    • Pode ocorrer um estouro tentando calcular log(0)e o software usa suas rotinas de tratamento de erros ou falha
    • O software pode assumir que todos os logaritmos podem ser calculados em um número fixo de etapas e retornar um valor grande, mas incorreto. Como os dois logaritmos seriam os mesmos, a diferença seria 0e e 0 = 1, resultando em1

Em outras palavras, seria dependente da implementação o que aconteceria e seria possível escrever um software que produza resultados corretos e previsíveis para todos os valores, mas valores aparentemente estranhos para 0/0isso, no entanto, ainda são internamente consistentes.


3
Esta questão é sobre dividir por zero nos números inteiros, e não existe algo como NaNos números inteiros.
David Hammen

3
Nenhuma CPU calculará logs e subtrairá para calcular o resultado da divisão. O tempo das instruções do logaritmo é várias ordens de magnitude maiores que uma divisão. Qual é o valor do log (0)?
27516 wallyk

1
@DavidHammen O OP nunca mencionou números inteiros e ninguém comentou a questão. Os números inteiros são mencionados apenas nas respostas.
CJ Dennis

@wallyk Eu já disse na minha resposta que esses logaritmos são very inefficientpara divisão. O custo da aritmética é (adição = subtração) <= multiplicação <= divisão. Se você não possui uma MPU que pode fazer a divisão no mesmo número de ciclos de clock da adição (geralmente um), a divisão é mais cara que a adição e subtração e geralmente mais cara que a multiplicação.
CJ Dennis
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.