마이너스 0을 식별하다

여느 때와 마찬가지로 나는 JS의 이상하거나 복잡한 부분을 깊이 연구하는 것을 좋아한다.몇 주 전에 나는 마이너스 0을 식별할 수 있는 방법을 고려하고 있었다.
너희들 중 몇몇은 아마 크게 놀랄 것이다.마이너스 0은 무엇입니까?영은 심지어 마이너스일 수 있습니까?그것은 IEEE에 근거할 수 있다!이것은 거의 모든 언어에 적용되는 표준 디지털 시스템이다.그래서 JS 디지털 시스템의 많은'괴상함'도 사실상 다른 언어의 표준이다!
그럼에도 불구하고 우리가 받은 입력이 -0인지 0인지 어떻게 알 수 있습니까?이것 괜찮아요?완전히 그렇지는 않지만, 이것은 재미있는 운동이다.
먼저 규칙을 만듭니다.우리는 매개 변수를 받아들이는 isZeroNegative이라는 함수가 있다.만약 0이 마이너스라면 우리는 반드시 true으로 돌아가야 하고, 0이 플러스라면 우리는 반드시 false으로 돌아가야 한다.우리는 함수에서 우리가 원하는 모든 코드를 작성할 수 있다.
function isZeroNegative(zero) {
  // some code
  return false; // default return
}

우리의 선택


이것은 보기에는 매우 간단하지만, 너는 그것이 약간 도전적이라는 것을 발견할 수 있을 것이다.너는 우선 그것이 0보다 낮은지 검사할 수 있다. 왜냐하면 이것은 보통 마이너스의 정의이기 때문이다. 그러나 이것은 안 된다.마이너스라도 수표는 false으로 돌아간다.-0 < 0 === false . Math.sign()은 아마도 너의 다음 추측일 것이다.어쨌든, 그것의 목적은 우리로 하여금 숫자가 마이너스인지 아닌지를 알게 하는 것이다.마이너스를 전달하면 -1, 정수라면 1으로 돌아간다.불행하게도, 만약 숫자가 0이라면, 마이너스든 정수든, 그것은 우리가 전달한 똑같은 0을 되돌려줄 것이다.Math.sign(-0) === -0 .
다음 옵션은 -0과 엄격한지 확인하는 것입니다.간단해!불행히도 엄격한 평등도 엄격하지 않다!-0 === 0 .
우리는 곧 선택의 여지가 없을 것이다.우리는 0이 나오지 않는 시스템을 통해 -0을 실행해야 한다.그것은 이 값보다 낮거나 높은 숫자를 되돌려야 하거나, 단지 다른 데이터 형식일 뿐이다.
그럼 엄격화는요?우리는 대응하는 문자열을 얻기 위해 모든 번호에서 .toString()으로 전화를 걸 수 있다.그리고 우리는 마이너스 번호를 검사할 수 있다.우리는 -4을 통해 (-4).toString()[0]의 마이너스 번호를 얻을 수 있다.불행히도, 다시 한 번 마이너스 0이 우리보다 한 걸음 앞섰다.빌어먹을 마이너스!(-0).toString()을 하면 "0"만 받는다.마이너스 문자열이 0이 됩니다.
고양이와 쥐를 잡는 놀이를 충분히 했다.우리들은 몇 가지 실제 답안을 되돌아봅시다.너 자신을 생각해 봐라.우리가 3단 전에 했던 말 기억나?

실제 답안


몇 가지 방법이 있다.이것들은 심지어 상세한 목록이 아닐 수도 있으니 다른 아이디어를 시도해 보세요!
나는 이 문제를 연구할 때 처음으로 this blog post을 만났다.이것은 Allen Wirfs Brock이 쓴 것입니다. 그는 현재 tc39에 있지만 2011년에 썼기 때문에 최근에 더 많은 방법을 사용할 수 있을 것입니다.나는 그곳에서 앞의 두 가지 해결 방안을 얻을 것이다.
우리가 탐색하고자 하는 첫 번째 해결 방안은 데이터 형식을 바꾸지 않기 때문에 성능이 가장 좋을 수도 있다.우리는 완전히 디지털 시스템에서 일한다.

수학과 IEEE


우리는 우선 우리가 -0을 사용하여 결과에 영향을 미칠 수 있는 수학 응용이 무엇인지를 고려해야 한다.가감법아니오, 이 두 사람의 작용은 0과 유사합니다.곱셈이냐 나눗셈이냐?곱셈은 우리에게 0(마이너스 또는 정)을 줄 것이다. 그러면 우리는 시작하는 곳부터 시작할 수 있다.영을 분자로 하는 제법은 곱셈과 같은 문제를 가져왔다!
저희가 -0을 분모로 하면요?만약 분자의 어떤 숫자에 0을 더하면 결과는 -Infinity이 될 것이다!-Infinity을 쉽게 검사할 수 있습니다!
그러나 분모상 -0만이 -Infinity을 초래할 수 있다는 것을 확인해야 한다.Jeff Waldon-Math.pow(2, -1074)을 반례로 제공했다.따라서, 우리는 우리가 처리하는 것이 0이라는 것을 확보하기 위해 엄격한 검사를 추가할 수 있다.
이 해결 방안을 통해 우리의 수상 코드는 지금이다.
function isZeroNegative(zero) {
  const isZero = zero === 0;
  const isNegative = 1 / zero === -Infinity;
  return isNegative && isZero;
}
흥미로운 것은 우리가 지금 같은 방법으로 더욱 완전한 증명 Math.sign()을 만들 수 있다는 것이다.이것은 낡은 것과 같지만, 지금은 제로를 잘 처리할 수 있다.부작용으로 Math.sign('')1이 아닌 0으로 돌아왔다.
Math.sign = function(num) {
    if (Number(num) !== Number(num)) return NaN;
    if (num === -Infinity) return -1;
    return 1 / num < 0 ? -1 : 1;
}

가장 엄격한 평등


이전의 해결 방안으로 돌아가서 시도해 봅시다.우리는 엄격한 평등(===)이 아직 엄격하지 않다는 것을 발견했다.어떤 평등이 이보다 더 엄격합니까?상수는?만약 엔진이 -00과 다르다는 것을 식별할 수 있다면, 우리는 어떤 방식으로 그것을 사용할 수 있을 것이다.
불행히도 const은 너무 엄격합니다.무슨 일이 발생하든지 간에 우리는 같은 범위 내에서 상량 변수를 재분배할 수 없다.설령 우리가 그것을 원래의 모양으로 다시 분배한다 하더라도.= 연산자만 존재하면 오류를 일으키기에 충분하다.
우리가 해야 할 일은 아래와 같다.
function isZeroNegative(zero) {
  if (zero !== 0) return false;

  const posZero = 0;
  try {
    posZero = num;
  } catch(e) {
    return true;
  }

  return false;
}
불행하게도, 설령 우리가 0을 얻는다 하더라도, 이것은 걸려 넘어질 것이다.앞에서 말한 바와 같이 =의 존재는 몇 가지 일을 일으키기에 충분하다.
JS에 또 다른 상수가 있나요?사실 있어요!Object.freeze을 사용하면 객체를 변경할 수 없습니다.
중요한 것은 동결된 대상의 속성을 변이하면 오류가 발생하지 않는다는 것이다.우리는 이렇게 해야 한다.이를 위해 우리는 더욱 직접적인 Object.defineProperty을 사용할 것이다.
function isZeroNegative(zero) {
  if (zero !== 0) return false;

  const posZero = Object.freeze({ val: 0 });
  try {
    Object.defineProperty(posZero, 'val', { value: num });
  } catch(e) {
    return true;
  }

  return false;
}
새 값이 0이 아니면 오류가 발생합니다!

현대 문자열 변환


우리가 이전에 소홀히 했던 해결 방안을 다시 한 번 토론합시다.(-0).toString()"0"으로 돌아온 것은 사실이지만, 더욱 현대적인 가선기인 .toLocaleString()이 있다.그것의 기능은 매우 강력하지만 최근에 나는 Infinity에서 그것을 사용하면 기호를 되돌려준다는 문제에 부딪혔다. ("∞일반 문자열 버전("무한")이 아니라.toLocaleString()에서 -0으로 전화를 걸어 실제로 "-0"으로 돌아오세요!
이 검색을 통해 다음과 같이 코드를 수정할 수 있습니다.
function isZeroNegative(zero) {
  if (zero !== 0) return false;

  return zero.toLocaleString()[0] === "-";
}
마지막은 가장 빠르고 간단하지만 가장 효과적이지는 않을 수도 있다. 마이너스 0을 찾는 것이 중요한 상황에서 중요할 수도 있다.

결론


왜 한 사람이 심지어 마이너스 0을 찾아야 합니까?나는 잠시 하나를 생각해 내지 못했다.이유는 필요없다.
이 글은 사유 과정에 대한 조사 같다.소프트웨어 엔지니어로서 문제를 해결하는 것은 매우 중요한 기능이다.해결 방안을 조사하는 방식이 해결 방안 자체보다 더 중요할 수도 있다.

좋은 웹페이지 즐겨찾기