Ecmascript bigint, от круглого к четному - PullRequest
0 голосов
/ 13 декабря 2018

Я использую функцию bigint от ESNext.При делении bigint округляется до 0. Возьмите следующий пример:

С числами:

> 3000 / 1578
1.9011406844106464

С bigint:

3000n / 1578n
1n

Вместо округления до0, я хотел бы написать функцию, которая может делать деление, но использовать округление банкиров (округление к четному).

Пример

function divide(a, b) {
  return a/b;
}

Я просто немного озадачен тем, как я могу написатьмоя divide функция, и используйте остаток, чтобы округлить до четного.Вот что я попробовал:

function divide(a, b) {
  let result = a/b;
  // if modulo is over half the divisor
  if ((a % b) * 2n > b) {
     // Add 1 if result is odd
     if (result % 2n === 1n) result++;
  } else {
     // Remove 1 if result is even
     if (result % 2n !== 1n) result--;
  }
  return result;
}

Это дает мне правильный результат для divide(3000n, 1578n), но я заметил, что это даст мне неправильный результат для divide(7n, 2n), который я ожидал округлить до 4n.

1 Ответ

0 голосов
/ 13 декабря 2018

Округление банкира влияет только на деления, где остаток составляет ровно половину делителя.Все остальные случаи получают нормальное округление.

Я думаю, что ваша функция должна быть изменена следующим образом:

function divide(a, b) {

  // Make A and B positive
  const aAbs = a > 0 ? a : -a;
  const bAbs = b > 0 ? b : -b;

  let result = aAbs/bAbs;
  const rem = aAbs % bAbs;
  // if remainder > half divisor, should have rounded up instead of down, so add 1
  if (rem * 2n > bAbs) {
      result ++;
  } else if (rem * 2n === bAbs) {
      // Add 1 if result is odd to get an even return value
      if (result % 2n === 1n) result++;
  }

  if (a > 0 !== b > 0) {
    // Either a XOR b is negative, so the result has to be
    // negative as well.
    return -result;
  } else {
    return result;
  }
}
console.log(divide(3000n, 1578n));
console.log(divide(7n, 2n));
console.log(divide(-7n, 2n));
...