Les opérateurs mathématiques *, /, +, -, ^ peuvent-ils être utilisés pour convertir un nombre différent de zéro en 1?

118

Je travaille avec le logiciel (Oracle Siebel) qui ne supporte que des expressions JavaScript avec les opérateurs se multiplient, se divisent, soustraient, ajouter et XOR ( *, /, -, +, ^). Je n'ai pas d'autres opérateurs tels que !ou ? :disponibles.

En utilisant les opérateurs ci-dessus, est-il possible de convertir un nombre en 1 s'il est différent de zéro et de le laisser 0 s'il est déjà nul? Le nombre peut être positif, zéro ou négatif.

Exemple:

var c = 55;

var d;  // d needs to set as 1

J'ai essayé c / c, mais il évalue NaNquand cest 0. ddoit être 0 quand cest 0.

c est une valeur monétaire, et il aura un maximum de deux chiffres de fin et 12 chiffres de tête.

J'essaie d'émuler une ifcondition en convertissant un nombre en un booléen 0 ou 1, puis en multipliant d'autres parties de l'expression.

Dave
la source
3
Les commentaires ne sont pas destinés à une discussion approfondie; cette conversation a été déplacée vers le chat .
Samuel Liew
10
@SamuelLiew Bien qu'il y ait beaucoup de commentaires, et certains d'entre eux devraient être supprimés ( discussion , réponse en commentaire ), la plupart d'entre eux sont en réalité des demandes de clarification ( par exemple ). Les commentaires demandant s'il s'agit d'un problème XY sont à la limite.
user202729
Oracle Siebel Numeric Operators, semble être un exposant: docs.oracle.com/cd/E95904_01/books/VBLANG/…
Derrick Moeller
2
@DerrickMoeller Il semble qu'il y ait une distinction entre Siebel VB et Siebel eScript. Dans ce dernier, il s'agit d'un xor au niveau du bit . Je ne sais pas lequel des deux s'applique ici.
CRice
3
@ user202729 une fois qu'un fil de commentaires entier devient trop long, nous n'allons pas traiter individuellement les commentaires différemment, car l'interface de mod créée par les administrateurs / développeurs SE préfère que nos actions par défaut soient "déplacer vers le chat" ou "supprimer tout". Si un commentaire est utile, il doit être modifié dans la question elle-même ou publié comme réponse. Si un commentaire est hors sujet, il aurait dû être auto-élagué / supprimé. Si vous souhaitez discuter de cette "fonctionnalité" du mod et / ou des indicateurs automatiques "trop ​​de commentaires" que les modérateurs obtiennent, veuillez en discuter sur Meta ou Meta.SE. Je vous remercie.
Samuel Liew

Réponses:

149

c / (c + 5e-324)devrait marcher. (La constante 5e-324est Number.MIN_VALUE, le plus petit nombre positif représentable.) Si x est 0, c'est exactement 0, et si x est différent de zéro (techniquement, si x est au moins 4,45014771701440252e-308, quel est le plus petit nombre différent de zéro autorisé dans le question, 0.01, est), les calculs en virgule flottante de JavaScript sont trop imprécis pour que la réponse soit différente de 1, donc elle sera exactement 1.

Joseph Sible-Réintégrer Monica
la source
1
vous devez d'abord convertir l'expression en booléen, car l'OP essaie de multiplier 0 et 1 avec other parts of the expression, et c / (c + 5e-324) * some_expressionne fonctionnera pas
phuclv
28
J'ai pris un bug et je l'
ai
1
@Medinoc oui, mais la question dit aussi qu'il n'y aura jamais plus de 2 chiffres après la virgule décimale, et 324 est bien plus que 2.
Joseph Sible-Reinstate Monica
1
C'est intéressant et cela pourrait fonctionner pour OP, mais je détesterais vraiment tomber sur ce genre de code en travaillant en équipe. À tout le moins, il devrait être bien documenté et testé.
Eric Duminil
1
@JosephSible Je sais, mais si vous le prenez vraiment de cette façon, la réponse la plus évidente devrait être Number(Boolean(n)), qui n'utilise aucun opérateur. Je n'ai pas dit que ce n'était pas la réponse que le PO recherchait, mais ce n'est pas la réponse à la question décrite par le PO. Cela devrait probablement améliorer la question.
user5532169
216

Utilisez l'expression n/n^0.

Si nn'est pas zéro:

 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.

Si nvaut zéro:

 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.

Comme vous pouvez le voir, toutes les valeurs non nulles sont converties en 1 et 0 reste à 0. Cela tire parti du fait qu'en JavaScript, NaN^0est 0.

Démo:

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

CRice
la source
45
TIL: Number.NaN ^ n === no_O (où nest un nombre fini)
zerkms
17
Il semble que lorsqu'il est utilisé comme opérande binaire, il NaNest commodément converti en zéro. Voir: Opérations au niveau du bit sur les non-nombres
CRice
3
@zerkms Peut-être ~~NaN === 0semble plus naturel
Bergi
8
@EnricoBorba Ce n'est pas l'exponentiation (qui utilise **), c'est un XOR au niveau du bit. Les opérations au niveau du bit ont une très faible priorité en javascript, donc la division se produira en premier.
CRice
3
^est l'opérateur xor au niveau du bit. Je doute que ^l'OP soit xor au niveau du bit lorsque tous les autres opérateurs sont des opérateurs arithmétiques. C'est probablement l'opérateur d'exponentiation ( **en JavaScript).
Salman A
17

(((c/c)^c) - c) * (((c/c)^c) - c) renverra toujours 1 pour les négatifs et les positifs et 0 pour 0.

C'est certainement plus déroutant que la réponse choisie et plus longue. Cependant, j'ai l'impression que c'est moins hacky et ne repose pas sur des constantes.

EDIT: Comme le mentionne @JosephSible, une version plus compacte de la mienne et de la version de @ CRice qui n'utilise pas de constantes est:

c/c^c-c
Kyle Wardle
la source
La réponse de CRice n'a pas été choisie, Joseph Sible l'a été. En toute honnêteté, je n'ai remarqué la réponse de CRice qu'après la publication.
Kyle Wardle
2
Il n'utilise cependant aucune constante, seulement les opérateurs et la variable donnée.
L3viathan
2
@JosephSible c/c^(c-c)est justec
Tavian Barnes
2
@JosephSible Je lisais ^comme exponentiation comme l'implique l'OP "multiplier, diviser, soustraire, additionner et exposer (*, /, -, +, ^ )". Si ^est XOR avec sa priorité JavaScript, je me trompe. J'ai demandé des éclaircissements sur le PO.
Tavian Barnes
2
@TavianBarnes ce n'est pas ce qu'OP a écrit; quelqu'un a modifié la question. Je l'ai restauré comme OP l'avait réellement demandé.
Joseph Sible-Réintégrer Monica
2

Une réponse très compliquée, mais qui ne dépend pas d'une précision limitée: si vous prenez x^(2**n), ce sera toujours égal à x+2**nsi x est nul, mais ce sera égal à x-2**nsi x a un un à la nième place. Ainsi, pour x = 0, (x^(2**n)-x+2**n)/(2**(n+1)sera toujours 1, mais il sera parfois nul pour x! = 0. Donc, si vous prenez le produit de (x^(2**n)-x+2**n)/(2**(n+1)sur tout n, puis XOR avec 1, vous obtiendrez la fonction souhaitée. Vous devrez cependant coder manuellement chaque facteur. Et vous devrez le modifier si vous utilisez des virgules flottantes.

Si vous avez l' ==opérateur, puis (x==0)^1fonctionne.

Accumulation
la source
3
Ni **ni ==disponible.
Joseph Sible-Réintégrer Monica