number.ts 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /**
  2. * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  6. */
  7. /**
  8. * Determine the number of digits in a floating point number
  9. * Find a number M such that round(M * v) - M * v <= delta.
  10. * If no such M exists, return -1.
  11. */
  12. export function getMantissaMultiplier(v: number, maxDigits: number, delta: number) {
  13. let m = 1, i;
  14. for (i = 0; i < maxDigits; i++) {
  15. const mv = m * v;
  16. if (Math.abs(Math.round(mv) - mv) <= delta) return i;
  17. m *= 10;
  18. }
  19. return -1;
  20. }
  21. export function integerDigitCount(v: number, delta: number) {
  22. const f = Math.abs(v);
  23. if (f < delta) return 0;
  24. return Math.floor(Math.log10(Math.abs(v))) + 1;
  25. }
  26. /**
  27. * Determine the maximum number of digits in a floating point array.
  28. * Find a number M such that round(M * v) - M * v <= delta.
  29. * If no such M exists, return -1.
  30. */
  31. export function getArrayDigitCount(xs: ArrayLike<number>, maxDigits: number, delta: number) {
  32. let mantissaDigits = 1;
  33. let integerDigits = 0;
  34. for (let i = 0, _i = xs.length; i < _i; i++) {
  35. if (mantissaDigits >= 0) {
  36. const t = getMantissaMultiplier(xs[i], maxDigits, delta);
  37. if (t < 0) mantissaDigits = -1;
  38. else if (t > mantissaDigits) mantissaDigits = t;
  39. }
  40. const abs = Math.abs(xs[i]);
  41. if (abs > delta) {
  42. const d = Math.floor(Math.log10(Math.abs(abs))) + 1;
  43. if (d > integerDigits) integerDigits = d;
  44. }
  45. }
  46. return { mantissaDigits, integerDigits };
  47. }
  48. export function isInteger(s: string) {
  49. s = s.trim();
  50. const n = parseInt(s, 10);
  51. return isNaN(n) ? false : n.toString() === s;
  52. }
  53. export function getPrecision(v: number) {
  54. if (!isFinite(v)) return 0;
  55. let e = 1;
  56. let p = 0;
  57. while (Math.round(v * e) / e !== v) {
  58. e *= 10;
  59. ++p;
  60. }
  61. return p;
  62. }
  63. export function toPrecision(v: number, precision: number) {
  64. return parseFloat(v.toPrecision(precision));
  65. }