Por que o zero negativo é importante?

59

Estou confuso sobre por que nos importamos com diferentes representações para zero positivo e negativo.

Eu me lembro vagamente de que a leitura afirma que ter uma representação zero negativa é extremamente importante na programação que envolve números complexos. Eu nunca tive a oportunidade de escrever código envolvendo números complexos, então estou um pouco confuso sobre por que isso seria o caso.

O artigo da Wikipedia sobre o conceito não é especialmente útil; ele só faz afirmações vagas sobre o zero assinado, tornando certas operações matemáticas mais simples em ponto flutuante, se eu entendi corretamente. Esta resposta lista algumas funções que se comportam de maneira diferente, e talvez algo possa ser inferido dos exemplos, se você estiver familiarizado com como eles podem ser usados. (Embora o exemplo particular das raízes quadradas complexas pareça errado errado , uma vez que os dois números são matematicamente equivalentes, a menos que eu tenha um mal-entendido.) Mas não consegui encontrar uma declaração clara do problema. tipo de problema em que você entraria se não estivesse lá. Os recursos mais matemáticos que consegui encontrar indicam que não há distinção entre os dois a partir de uma perspectiva matemática, e o artigo da Wikipedia parece sugerir que isso raramente é visto fora da computação, além de descrever limites.

Então, por que um zero negativo é valioso na computação? Tenho certeza que estou sentindo falta de algo.

    
por jpmc26 01.05.2015 / 04:10
fonte

5 respostas

64

Você precisa ter em mente que, na aritmética de FPU, 0 não necessariamente tem que significar exatamente zero, mas também valor pequeno demais para ser representado usando determinado tipo de dados, por exemplo.

a = -1 / 1000000000000000000.0

a é muito pequeno para ser representado corretamente por float (32 bits), então é "arredondado" para -0.

Agora, digamos que nossa computação continue:

b = 1 / a

Como a é float, resultará em -infinity, o que está muito longe da resposta correta de -1000000000000000000.0

Agora vamos calcular b se não houver -0 (então a é arredondado para +0):

b = 1 / +0
b = +infinity

O resultado está errado novamente por causa do arredondamento, mas agora está "mais errado" - não apenas numericamente, mas mais importante por causa do sinal diferente (resultado da computação é + infinito, resultado correto é -1000000000000000000.0).

Você ainda pode dizer que isso não importa, pois ambos estão errados. O importante é que há muitas aplicações numéricas em que o resultado mais importante da computação é o sinal - por exemplo, ao decidir se virar à esquerda ou à direita no cruzamento usando algum algoritmo de aprendizado de máquina, você pode interpretar o valor positivo = > vire à esquerda, valor negativo = > vire à direita, a "magnitude" real do valor é apenas "coeficiente de confiança".

    
por 01.05.2015 / 17:30
fonte
8

Primeiro, como você cria um -0? Existem duas maneiras: (1) fazer uma operação de ponto flutuante onde o resultado matemático é negativo, mas tão próximo de zero que ele é arredondado para zero e não para um número diferente de zero. Esse cálculo dará um -0. (b) Certas operações envolvendo zeros: Multiplique um zero positivo por um número negativo ou divida um zero positivo por um número negativo ou anule um zero positivo.

Ter um zero negativo simplifica um pouco a multiplicação e a divisão, o sinal de x * y ou x / y é sempre o sinal de x, exclusivo ou o sinal de y. Sem zero negativo, teria que haver alguma verificação extra para substituir -0 por +0.

Existem algumas situações muito raras em que é útil. Você pode verificar se o resultado de uma multiplicação ou divisão é matematicamente maior ou menor que zero, mesmo se houver um underflow (contanto que você saiba que o resultado não é um zero matemático). Não me lembro de ter escrito código onde isso faz diferença.

Otimizando compiladores odeiam -0. Por exemplo, você não pode substituir x + 0.0 por x, porque o resultado não deve ser x se x for -0.0. Você não pode substituir x * 0.0 por 0.0, porque o resultado deve ser -0.0 se x < 0 ou x é -0,0.

    
por 02.05.2015 / 18:41
fonte
6

C # Double que está em conformidade com o IEEE 754

    double a = 3.0;
    double b = 0.0;
    double c = -0.0;

    Console.WriteLine(a / b);
    Console.WriteLine(a / c);

impressões:

Infinity
-Infinity

na verdade, para explicar um pouco ...

Double d = -0.0; 

Isso significa algo muito mais próximo de d = The Limit of x as x approaches 0- ou The Limit of x as x approaches 0 from the negatives .

Para abordar o comentário de Philipp ...

Basicamente, zero negativo significa underflow.

Há muito pouco uso prático para zero negativo, se houver ...

por exemplo, este código (novamente C #):

double a = -0.0;
double b = 0.0;

Console.WriteLine(a.Equals(b));
Console.WriteLine(a==b);
Console.WriteLine(Math.Sign(a));

produz este resultado:

True
True
0

Para explicar informalmente, todos os valores especiais que um ponto flutuante IEEE 754 pode ter (infinito positivo, infinito negativo, NAN, -0.0) não têm significado no sentido prático. Eles não podem representar nenhum valor físico ou qualquer valor que faça sentido no cálculo do "mundo real". O que eles querem dizer é basicamente isto:

  • infinito positivo significa um estouro no final positivo que um ponto flutuante pode representar
  • infinito negativo significa um estouro no final positivo que um ponto flutuante pode representar
  • zero negativo significa um estouro negativo e os operandos tinham sinais opostos
  • positivo zero pode significar um estouro negativo e os operandos tinham o mesmo sinal
  • NAN significa que seu cálculo é indefinidamente completo, como sqrt(-7) , ou não tem um limite como 0/0 ou como PositiveInfinity/PositiveInfinity
por 01.05.2015 / 16:57
fonte
5

A questão sobre como isso se relaciona com os cálculos de números complexos realmente fica no centro do motivo pelo qual tanto o +0 quanto o -0 existem em ponto flutuante. Se você estuda Análise Complexa, você rapidamente descobre que funções contínuas de Complexo para Complexo normalmente não podem ser tratadas como 'valor único' a menos que se adote a 'ficção educada' de que as saídas formam o que é conhecido como 'superfície de Riemann'. Por exemplo, o logaritmo complexo atribui a cada entrada infinitas muitas saídas; quando você as conecta para formar uma saída contínua, você acaba com todas as partes reais formando uma superfície 'saca-rolhas infinita' ao redor da origem. Uma curva contínua que cruza o eixo real "para baixo a partir do lado positivo-imaginário" e outra curva que "envolve o pólo" e cruza o eixo real "para cima a partir do lado negativo imaginário" assumirá valores diferentes no eixo real porque eles passam por diferentes 'folhas' da superfície de Riemann.

Agora, aplique-o a um programa numérico que calcule o uso de ponto flutuante complexo. A ação tomada após um determinado cálculo pode ser muito diferente dependendo de qual 'planilha' o programa está atualmente 'ligado', e o sinal do último resultado calculado provavelmente informa qual 'planilha'. Agora suponha que o resultado fosse zero? Lembre-se, aqui 'zero' significa realmente 'pequeno demais para representar corretamente'. Mas se o cálculo puder organizar para preservar o sinal (ou seja, lembrar qual "planilha") quando o resultado for zero, o código poderá verificar o sinal e executar a ação correta mesmo nessa situação.

    
por 26.02.2016 / 16:04
fonte
1

O motivo é mais simples que o normal

É claro que há muitos hacks que parecem muito legais e são úteis (como arredondar para -0.0 ou +0.0 , mas suponha que temos uma representação de int assinado com menos / sinal de mais no início (eu sei que é resolvido pelo código binário U2 em números inteiros geralmente, mas assume uma representação menos complexa de duplo):

0 111 = 7
^ sign

E se houver um número negativo?

1 111 = -7

Ok, simples assim. Então vamos representar 0:

0 000 = 0

Tudo bem também. Mas e quanto a 1 000 ? Tem que ser um número proibido? Melhor não.

Então, vamos supor que haja dois tipos de zero:

0 000 = +0
1 000 = -0

Bem, isso simplificará nossos cálculos e, felizmente, oferecerá alguns recursos adicionais. Portanto, +0 e -0 são provenientes apenas de questões de representação binária.

    
por 01.05.2015 / 18:07
fonte