Czy można użyć operatorów matematycznych *, /, +, -, ^ do konwersji liczby niezerowej na 1?

118

Pracuję z oprogramowaniem (Oracle Siebel), który obsługuje tylko wyrażeń JavaScript z operatorami mnożenie, dzielenie, odejmowanie, dodawanie i XOR ( *, /, -, +, ^). Nie mam innych operatorów, takich jak !lub ? :dostępnych.

Czy za pomocą powyższych operatorów można przekonwertować liczbę na 1, jeśli jest różna od zera, i pozostawić ją na 0, jeśli jest już zero? Liczba może być dodatnia, zerowa lub ujemna.

Przykład:

var c = 55;

var d;  // d needs to set as 1

Próbowałem c / c, ale oblicza, NaNkiedy cwynosi 0. dMusi być 0, kiedy cwynosi 0.

c to wartość waluty, która może mieć maksymalnie dwie cyfry końcowe i 12 cyfr wiodących.

Próbuję emulować ifwarunek, konwertując liczbę na wartość logiczną 0 lub 1, a następnie mnożąc inne części wyrażenia.

dave
źródło
3
Komentarze nie służą do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Samuel Liew
10
@SamuelLiew Chociaż komentarzy jest dużo, a niektóre z nich należy usunąć ( dyskusja , odpowiedź w komentarzu ), większość z nich to tak naprawdę prośby o wyjaśnienia ( na przykład ). Komentarze pytające, czy jest to problem XY, są na granicy.
user202729
Oracle Siebel Numeric Operators, wydaje się być wykładnikiem: docs.oracle.com/cd/E95904_01/books/VBLANG/ ...
Derrick Moeller
2
@DerrickMoeller Wydaje się, że istnieje różnica między Siebel VB a Siebel eScript. W tym drugim przypadku jest to bitowe xor . Nie jestem pewien, który z nich ma tutaj zastosowanie.
CRice
3
@ user202729 Gdy cały wątek komentarzy stanie się zbyt długi, nie będziemy indywidualnie traktować komentarzy w inny sposób, ponieważ interfejs modów stworzony przez administratorów / deweloperów SE woli, aby nasze domyślne akcje to „przenieś na czat” lub „usuń wszystko”. Jeśli jakikolwiek komentarz jest przydatny, należy go zredagować w samym pytaniu lub zamieścić jako odpowiedź. Jeśli jakikolwiek komentarz jest niezwiązany z tematem, powinien zostać przycięty / usunięty samodzielnie. Jeśli chciałbyś omówić tę "funkcję" i / lub "zbyt wiele komentarzy" auto flag, które dostają moderatorzy, przynieś to do dyskusji na Meta lub Meta.SE. Dziękuję Ci.
Samuel Liew

Odpowiedzi:

149

c / (c + 5e-324)powinno działać. (Stała 5e-324to Number.MIN_VALUEnajmniejsza reprezentowalna liczba dodatnia.) Jeśli x jest równe 0, to jest dokładnie 0, a jeśli x jest różne od zera (technicznie rzecz biorąc, jeśli x wynosi co najmniej 4,45014771701440252e-308, czyli najmniejszą dopuszczalną liczbą niezerową w pytanie, 0,01, jest), obliczenia zmiennoprzecinkowe JavaScript są zbyt nieprecyzyjne, aby odpowiedź była inna niż 1, więc wyjdzie jako dokładnie 1.

Joseph Sible - przywróć Monikę
źródło
1
musisz najpierw przekonwertować wyrażenie na bool, ponieważ OP próbuje pomnożyć 0 i 1 przez other parts of the expressioni c / (c + 5e-324) * some_expressionnie zadziała
phuclv
28
Zrobiłem
1
@Medinoc tak, ale pytanie mówi również, że nigdy nie będzie więcej niż 2 cyfry po przecinku, a liczba 324 to dużo więcej niż 2.
Joseph Sible-Reinstate Monica
1
To interesujące i może działać w OP, ale naprawdę nie chciałbym natknąć się na tego rodzaju kod podczas pracy w zespole. Powinien być przynajmniej dobrze udokumentowany i przetestowany.
Eric Duminil
1
@JosephSible Wiem, ale jeśli naprawdę traktujesz to w ten sposób, najbardziej oczywistą odpowiedzią powinna być odpowiedź Number(Boolean(n))bez operatora. Nie powiedziałem, że nie jest to odpowiedź, której szukał PO, ale to nie jest odpowiedź na pytanie, które opisał PO. Prawdopodobnie powinno to poprawić pytanie.
user5532169
216

Użyj wyrażenia n/n^0 .

Jeśli nnie jest zerem:

 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.

Jeśli nwynosi 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.

Jak widać, wszystkie niezerowe wartości są konwertowane na 1, a 0 pozostaje na 0. Wykorzystuje to fakt, że w JavaScript, NaN^0 wynosi 0.

Próbny:

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

CRice
źródło
45
TIL: Number.NaN ^ n === no_O (gdzie njest liczbą skończoną)
zerkms
17
Wydaje się, że gdy jest używany jako operand bitowy, NaNjest dogodnie konwertowany na zero. Zobacz: Operacje bitowe na liczbach innych niż liczby
CRice
3
@zerkms Może ~~NaN === 0wydaje się bardziej naturalne
Bergi,
8
@EnricoBorba To nie jest potęgowanie (które używa **), jest to bitowy XOR. Operacje bitowe mają bardzo niski priorytet w javascript, więc podział nastąpi najpierw.
CRice
3
^jest bitowym operatorem xor. Wątpię, czy ^w OP jest bitowe xor, gdy wszystkie inne operatory są operatorami arytmetycznymi. Prawdopodobnie jest to operator potęgowania ( **w JavaScript).
Salman A
17

(((c/c)^c) - c) * (((c/c)^c) - c) zawsze zwróci 1 dla negatywów i pozytywów, a 0 dla 0.

Jest zdecydowanie bardziej zagmatwana niż wybrana odpowiedź i dłuższa. Jednak wydaje mi się, że jest mniej hakerski i nie opiera się na stałych.

EDYCJA: Jak wspomina @JosephSible, bardziej kompaktowa wersja mojej i @ CRice, która nie używa stałych, to:

c/c^c-c
Kyle Wardle
źródło
Odpowiedź CRice'a nie została wybrana, był nim Joseph Sible. Szczerze mówiąc, nie zauważyłem odpowiedzi CRice aż do wysłania.
Kyle Wardle
2
Nie używa jednak stałych, tylko operatory i daną zmienną.
L3viathan
2
@JosephSible c/c^(c-c)jest po prostuc
Tavian Barnes
2
@JosephSible, które czytałem ^jako potęgowanie, jak sugeruje OP „mnożenie, dzielenie, odejmowanie, dodawanie i wykładnik (*, /, -, +, ^ )”. Jeśli ^jest XOR z pierwszeństwem JavaScript, to się mylę. Poprosiłem o wyjaśnienie w sprawie PO.
Tavian Barnes
2
@TavianBarnes to nie to, co napisał OP; ktoś zredagował pytanie. Przywróciłem to, o co prosił OP.
Joseph Sible-Reinstate Monica
2

Bardzo skomplikowana odpowiedź, ale nie zależy od ograniczonej precyzji: jeśli weźmiesz x^(2**n), zawsze będzie równe, x+2**njeśli x będzie równe zero, ale będzie równe, x-2**njeśli x ma jedynkę na n-tym miejscu. Zatem dla x = 0, (x^(2**n)-x+2**n)/(2**(n+1)zawsze będzie wynosić 1, ale czasami będzie wynosić zero dla x! = 0. Więc jeśli weźmiesz produkt(x^(2**n)-x+2**n)/(2**(n+1) po wszystkich n, a następnie XOR to z 1, otrzymasz pożądaną funkcję. Musisz jednak ręcznie zakodować każdy czynnik. Będziesz musiał to zmodyfikować, jeśli używasz punktów zmiennoprzecinkowych.

Jeśli masz ==operatora, to (x==0)^1działa.

Akumulacja
źródło
3
Ani **ani nie ==jest dostępne.
Joseph Sible-Reinstate Monica