1

Given that Math.ceil(1/3) yields 1, how do I get that 1 (or 1n) from BigInt input values of 1n and 3n? Obviously Math.ceil(Number(1n)/Number(3n)) would work but some bigints might be too big for that approach.

3
  • BigInt only deals with integers. There are no fractions, so no need for the ceil() function. Commented Aug 19, 2022 at 0:03
  • @JaromandaX That's my point. It doesn't return a fraction, so you can't get the ceiling of it. Commented Aug 19, 2022 at 0:19
  • @Barmar - ahh, I see what you're saying now :p sorry Commented Aug 19, 2022 at 0:20

2 Answers 2

4

Create a simple function

Note: the .toString() is ONLY so the console output is shown here

const ceilN = (n, d) => n / d + (n % d ? 1n : 0n)

console.log(ceilN(120n, 3n).toString()); // 40
console.log(ceilN(121n, 3n).toString()); // 41
console.log(ceilN(122n, 3n).toString()); // 41
console.log(ceilN(123n, 3n).toString()); // 41

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. To make it work with signed inputs I believe it needs to be +(n%d>0n?1n:0n)
Feels close, but doesn't work for ceilN(121n, -3n), even though works for ceilN(-121n, 3n).
yeah, I hate modulo on negatives :p
For positive inputs, this can be made more efficient: (n, d) => (n + d - 1n) / d; that approach gets a bit messy though if it needs to handle negative inputs as well.
0

The accepted answer does not handle negative bigints correctly.

We must handle each scenario correctly, plus it's easier to use a custom modulo operator rather than JavaScript's useless signed remainder operator (%).

Let's first patch the modulo operator:

const bigint_pos_mod = (a, b) => {
    return ((a % b) + b) % b;
};

Now, observe that bigint division is truncated toward zero (and not, for example, floored):

For BigInt division, the result is the quotient of the two operands truncated towards zero, and the remainder is discarded.

In case the division was not smoothly done (there is a remainder), we aim to increase by one to achieve a ceiling. However, as truncation is towards zero, this already takes care of the increase in case of negative numbers, thus we are only interested in > 0n.

const bigint_ceil = (numerator, denominator) => {
    const is_negative = (false
        || (numerator <  0n && denominator >= 0n)
        || (numerator >= 0n && denominator <  0n)
    );

    return (0n
        + numerator / denominator
        + (is_negative ? 0n : bigint_pos_mod(numerator, denominator) > 0n ? 1n : 0n)
    );
};

Note that if you wanted to floor, you would decrease by one, and if you wanted to round or truncate toward zero you would take a slightly different approach by paying attention to the sign.

The following test cases pass like flying colors:

const bigint_pos_mod = (a, b) => {
    return ((a % b) + b) % b;
};

const bigint_ceil = (numerator, denominator) => {
    const is_negative = (false
        || (numerator <  0n && denominator >= 0n)
        || (numerator >= 0n && denominator <  0n)
    );

    return (0n
        + numerator / denominator
        + (is_negative ? 0n : bigint_pos_mod(numerator, denominator) > 0n ? 1n : 0n)
    );
};

console.log("Both numerator and denominator positive.");
console.log(bigint_ceil(120n, 3n).toString()); // 40
console.log(bigint_ceil(121n, 3n).toString()); // 41
console.log(bigint_ceil(122n, 3n).toString()); // 41
console.log(bigint_ceil(123n, 3n).toString()); // 41

console.log("Numerator negative.");
console.log(bigint_ceil(-120n, 3n).toString()); // -40
console.log(bigint_ceil(-121n, 3n).toString()); // -40
console.log(bigint_ceil(-122n, 3n).toString()); // -40
console.log(bigint_ceil(-123n, 3n).toString()); // -41

console.log("Denominator negative.");
console.log(bigint_ceil(120n, -3n).toString()); // -40
console.log(bigint_ceil(121n, -3n).toString()); // -40
console.log(bigint_ceil(122n, -3n).toString()); // -40
console.log(bigint_ceil(123n, -3n).toString()); // -41

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.