* Round the parsed number to the specified number of decimal places * This function changes the parsedNumber in-place
(parsedNumber: ParsedNumber, minFrac: number, maxFrac: number)
| 455 | * This function changes the parsedNumber in-place |
| 456 | */ |
| 457 | function roundNumber(parsedNumber: ParsedNumber, minFrac: number, maxFrac: number) { |
| 458 | if (minFrac > maxFrac) { |
| 459 | throw new RuntimeError( |
| 460 | RuntimeErrorCode.INVALID_NUMBER_OF_DIGITS_AFTER_FRACTION, |
| 461 | ngDevMode && |
| 462 | `The minimum number of digits after fraction (${minFrac}) is higher than the maximum (${maxFrac}).`, |
| 463 | ); |
| 464 | } |
| 465 | |
| 466 | let digits = parsedNumber.digits; |
| 467 | let fractionLen = digits.length - parsedNumber.integerLen; |
| 468 | const fractionSize = Math.min(Math.max(minFrac, fractionLen), maxFrac); |
| 469 | |
| 470 | // The index of the digit to where rounding is to occur |
| 471 | let roundAt = fractionSize + parsedNumber.integerLen; |
| 472 | let digit = digits[roundAt]; |
| 473 | |
| 474 | if (roundAt > 0) { |
| 475 | // Drop fractional digits beyond `roundAt` |
| 476 | digits.splice(Math.max(parsedNumber.integerLen, roundAt)); |
| 477 | |
| 478 | // Set non-fractional digits beyond `roundAt` to 0 |
| 479 | for (let j = roundAt; j < digits.length; j++) { |
| 480 | digits[j] = 0; |
| 481 | } |
| 482 | } else { |
| 483 | // We rounded to zero so reset the parsedNumber |
| 484 | fractionLen = Math.max(0, fractionLen); |
| 485 | parsedNumber.integerLen = 1; |
| 486 | digits.length = Math.max(1, (roundAt = fractionSize + 1)); |
| 487 | digits[0] = 0; |
| 488 | for (let i = 1; i < roundAt; i++) digits[i] = 0; |
| 489 | } |
| 490 | |
| 491 | if (digit >= 5) { |
| 492 | if (roundAt - 1 < 0) { |
| 493 | for (let k = 0; k > roundAt; k--) { |
| 494 | digits.unshift(0); |
| 495 | parsedNumber.integerLen++; |
| 496 | } |
| 497 | digits.unshift(1); |
| 498 | parsedNumber.integerLen++; |
| 499 | } else { |
| 500 | digits[roundAt - 1]++; |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | // Pad out with zeros to get the required fraction length |
| 505 | for (; fractionLen < Math.max(0, fractionSize); fractionLen++) digits.push(0); |
| 506 | |
| 507 | let dropTrailingZeros = fractionSize !== 0; |
| 508 | // Minimal length = nb of decimals required + current nb of integers |
| 509 | // Any number besides that is optional and can be removed if it's a trailing 0 |
| 510 | const minLen = minFrac + parsedNumber.integerLen; |
| 511 | // Do any carrying, e.g. a digit was rounded up to 10 |
| 512 | const carry = digits.reduceRight(function (carry, d, i, digits) { |
| 513 | d = d + carry; |
| 514 | digits[i] = d < 10 ? d : d - 10; // d % 10 |
no test coverage detected
searching dependent graphs…