Os operadores matemáticos *, /, +, -, ^ podem ser usados ​​para converter um número diferente de zero em 1?

118

Eu estou trabalhando com software (Oracle Siebel), que suporta apenas expressões JavaScript com operadores multiplicar, dividir, subtrair, adicionar e XOR ( *, /, -, +, ^). Não tenho outras operadoras como as !ou ? :disponíveis.

Usando os operadores acima, é possível converter um número para 1 se for diferente de zero e deixá-lo 0 se já for zero? O número pode ser positivo, zero ou negativo.

Exemplo:

var c = 55;

var d;  // d needs to set as 1

Eu tentei c / c, mas avalia NaNquando cé 0. dprecisa ser 0 quando cé 0.

c é um valor monetário e terá no máximo dois dígitos finais e 12 dígitos iniciais.

Estou tentando emular uma ifcondição convertendo um número em um booleano 0 ou 1 e, em seguida, multiplicando outras partes da expressão.

Dave
fonte
3
Os comentários não são para discussão extensa; esta conversa foi movida para o chat .
Samuel Liew
10
@SamuelLiew Embora existam muitos comentários, e alguns deles devam ser removidos ( discussão , resposta em comentário ), a maioria deles são realmente pedidos de esclarecimento ( por exemplo ). Comentários perguntando se é um problema XY são limítrofes.
user202729
Oracle Siebel Numeric Operators, parece ser Expoente: docs.oracle.com/cd/E95904_01/books/VBLANG/…
Derrick Moeller
2
@DerrickMoeller Parece que há uma distinção entre Siebel VB e Siebel eScript. No último, é um xor bit a bit . Não tenho certeza de qual dos dois se aplica aqui.
CRice
3
@ user202729 uma vez que qualquer thread de comentário inteiro fique muito longo, não vamos tratar os comentários individualmente de maneira diferente, já que a interface mod criada por administradores / devs SE prefere que nossas ações padrão sejam "mover para o bate-papo" ou "excluir tudo". Se algum comentário for útil, deve ser editado na própria pergunta ou postado como uma resposta. Se algum comentário estiver fora do tópico, ele deve ter sido auto-removido / excluído. Se você gostaria de discutir este mod "recurso" e / ou os "muitos comentários" que os moderadores de sinalizadores automáticos obtêm, traga-o para discussão no Meta ou Meta.SE. Obrigado.
Samuel Liew

Respostas:

149

c / (c + 5e-324)Deveria trabalhar. (A constante 5e-324éNumber.MIN_VALUE , o menor número positivo representável.) Se x for 0, isso é exatamente 0, e se x for diferente de zero (tecnicamente, se x for pelo menos 4,45014771701440252e-308, que é o menor número diferente de zero permitido no questão, 0,01, é), a matemática de ponto flutuante do JavaScript é muito imprecisa para que a resposta seja diferente de 1, portanto, será exatamente 1.

Joseph Sible-Reintegrar Monica
fonte
1
você precisa converter a expressão em bool primeiro, já que o OP está tentando multiplicar 0 e 1 por other parts of the expression, e c / (c + 5e-324) * some_expressionnão funcionará
phuclv
28
Obteve um bug e o transformou em um recurso lá
Chirag Bhatia - chirag64
1
@Medinoc sim, mas a pergunta também diz que nunca haverá mais do que 2 dígitos após o ponto decimal, e 324 é muito mais do que 2.
Joseph Sible-Reintegrar Monica
1
É interessante e pode funcionar para OP, mas eu realmente odiaria encontrar esse tipo de código ao trabalhar em uma equipe. No mínimo, deve ser bem documentado e testado.
Eric Duminil
1
@JosephSible eu sei, mas se você realmente entender assim, a resposta mais óbvia deveria ser Number(Boolean(n)), que não usa operadora. Eu não disse que não era essa a resposta que o OP estava procurando, mas essa não é a resposta à pergunta que o OP descreveu. Provavelmente deve melhorar a questão.
user5532169
216

Use a expressão n/n^0.

Se nnão for zero:

 Step    Explanation
------- -------------------------------------------------------------------------------
 n/n^0   Original expression.
 1^0     Any number divided by itself equals 1. Therefore n/n becomes 1.
 1       1 xor 0 equals 1.

Se nfor zero:

 Step    Explanation
------- -------------------------------------------------------------------------------
 n/n^0   Original expression.
 0/0^0   Since n is 0, n/n is 0/0.
 NaN^0   Zero divided by zero is mathematically undefined. Therefore 0/0 becomes NaN.
 0^0     In JavaScript, before any bitwise operation occurs, both operands are normalized.
         This means NaN becomes 0.
 0       0 xor 0 equals 0.

Como você pode ver, todos os valores diferentes de zero são convertidos em 1 e 0 permanece em 0. Isso aproveita o fato de que, em JavaScript, NaN^0é 0.

Demo:

[0, 1, 19575, -1].forEach(n => console.log(`${n} becomes ${n/n^0}.`))

CRice
fonte
45
TIL: Number.NaN ^ n === no_O (onde né um número finito)
zerkms
17
Parece que quando usado como um operando bit a bit, NaNé convenientemente convertido para zero. Veja: Operações bit a bit em não números
CRice
3
@zerkms Talvez ~~NaN === 0pareça mais natural
Bergi,
8
@EnricoBorba Não é exponenciação (que usa **), é um XOR bit a bit. Operações bit a bit têm uma precedência muito baixa em javascript, então a divisão acontecerá primeiro.
CRice
3
^é o operador xor bit a bit. Duvido que ^no OP seja xor bit a bit quando todos os outros operadores são operadores aritméticos. Provavelmente é o operador de exponenciação ( **em JavaScript).
Salman A
17

(((c/c)^c) - c) * (((c/c)^c) - c) sempre retornará 1 para negativos e positivos e 0 para 0.

É definitivamente mais confuso do que a resposta escolhida e mais longo. No entanto, eu sinto que é menos hacky e não depende de constantes.

EDITAR: Como @JosephSible menciona, uma versão mais compacta da minha e a versão do @CRice que não usa constantes é:

c/c^c-c
Kyle Wardle
fonte
A resposta de CRice não foi escolhida, Joseph Sible foi. Com toda a honestidade, não percebi a resposta de CRice até depois de postar.
Kyle Wardle
2
No entanto, ele não usa constantes, apenas os operadores e a variável fornecida.
L3viathan
2
@JosephSible c/c^(c-c)é apenasc
Tavian Barnes
2
@JosephSible eu estava lendo ^como exponenciação implícita no OP "multiplique, divida, subtraia, adicione e exponente (*, /, -, +, ^ )". Se ^for XOR com sua precedência de JavaScript, estou errado. Pedi esclarecimentos sobre o OP.
Tavian Barnes
2
@TavianBarnes não é o que OP escreveu; alguém editou a pergunta. Eu o restaurei da maneira que o OP realmente pediu.
Joseph Sible-Reintegrar Monica
2

Uma resposta muito complicada, mas que não depende de precisão limitada: se você pegar x^(2**n), isso sempre será igual a x+2**nse x for zero, mas será igual a x-2**nse x tiver um na enésima casa. Assim, para x = 0, (x^(2**n)-x+2**n)/(2**(n+1)sempre será 1, mas às vezes será zero para x! = 0. Portanto, se você pegar o produto de (x^(2**n)-x+2**n)/(2**(n+1)todo n, então XOR isso com 1, você obterá a função desejada. Você terá que codificar manualmente cada fator, no entanto. E você terá que modificar isso se estiver usando pontos flutuantes.

Se você tiver a ==operadora, então (x==0)^1funciona.

Acumulação
fonte
3
Nem **nem ==está disponível.
Joseph Sible-Reintegrar Monica