Add 1/6 fractions, add test coverage
This commit is contained in:
parent
13a9e855bc
commit
ed383ae56d
@ -1,5 +1,6 @@
|
||||
import {
|
||||
convertNumberToRomanNumeral,
|
||||
formatNumberToFraction,
|
||||
roundToString,
|
||||
roundToNumber,
|
||||
} from '@/utility/number';
|
||||
@ -17,6 +18,28 @@ describe('number', () => {
|
||||
expect(convertNumberToRomanNumeral(9)).toBe('IX');
|
||||
expect(convertNumberToRomanNumeral(10)).toBe('X');
|
||||
});
|
||||
it('formats decimals to fractions', () => {
|
||||
expect(formatNumberToFraction(0.1666666)).toBe('+1/6');
|
||||
expect(formatNumberToFraction(0.25)).toBe('+1/4');
|
||||
expect(formatNumberToFraction(0.3333333)).toBe('+1/3');
|
||||
expect(formatNumberToFraction(0.5)).toBe('+1/2');
|
||||
expect(formatNumberToFraction(0.6666666)).toBe('+2/3');
|
||||
expect(formatNumberToFraction(0.75)).toBe('+3/4');
|
||||
expect(formatNumberToFraction(0.8333333)).toBe('+5/6');
|
||||
expect(formatNumberToFraction(1.6666666)).toBe('+1 2/3');
|
||||
expect(formatNumberToFraction(1.75)).toBe('+1 3/4');
|
||||
expect(formatNumberToFraction(10.75)).toBe('+10 3/4');
|
||||
expect(formatNumberToFraction(-0.1666666)).toBe('-1/6');
|
||||
expect(formatNumberToFraction(-0.25)).toBe('-1/4');
|
||||
expect(formatNumberToFraction(-0.3333333)).toBe('-1/3');
|
||||
expect(formatNumberToFraction(-0.5)).toBe('-1/2');
|
||||
expect(formatNumberToFraction(-0.6666666)).toBe('-2/3');
|
||||
expect(formatNumberToFraction(-0.75)).toBe('-3/4');
|
||||
expect(formatNumberToFraction(-0.8333333)).toBe('-5/6');
|
||||
expect(formatNumberToFraction(-1.6666666)).toBe('-1 2/3');
|
||||
expect(formatNumberToFraction(-1.75)).toBe('-1 3/4');
|
||||
expect(formatNumberToFraction(-10.75)).toBe('-10 3/4');
|
||||
});
|
||||
describe('rounds to a', () => {
|
||||
it('string', () => {
|
||||
expect(roundToString(1.2345, 1)).toBe('1.2');
|
||||
|
||||
@ -21,14 +21,22 @@ const gcd = (a: number, b: number): number => {
|
||||
}
|
||||
};
|
||||
|
||||
const FRACTION_TOLERANCE = 0.011;
|
||||
const STICKY_DECIMALS = [0.25, 0.33, 0.5, 0.66, 0.75];
|
||||
const MAX_FRACTION_LENGTH = 4; // Permit 1/64 but not 1/100
|
||||
|
||||
const formatDecimalToFraction = (_decimal: number) => {
|
||||
// Prevent imprecision which causes numbers such as,
|
||||
// 0.1 to equal 0.10000000000000009
|
||||
const decimal = parseFloat(_decimal.toPrecision(8));
|
||||
if (Math.abs(Math.abs(decimal) - 0.33) < 0.011) {
|
||||
if (Math.abs(Math.abs(decimal) - 0.167) <= FRACTION_TOLERANCE) {
|
||||
return '1/6';
|
||||
} else if (Math.abs(Math.abs(decimal) - 0.333) <= FRACTION_TOLERANCE) {
|
||||
return '1/3';
|
||||
} else if (Math.abs(Math.abs(decimal) - 0.66) <= 0.011) {
|
||||
} else if (Math.abs(Math.abs(decimal) - 0.667) <= FRACTION_TOLERANCE) {
|
||||
return '2/3';
|
||||
} else if (Math.abs(Math.abs(decimal) - 0.833) <= FRACTION_TOLERANCE) {
|
||||
return '5/6';
|
||||
} else {
|
||||
const length = decimal.toString().length - 2;
|
||||
|
||||
@ -44,19 +52,15 @@ const formatDecimalToFraction = (_decimal: number) => {
|
||||
}
|
||||
};
|
||||
|
||||
const STICKY_THRESHOLD = 0.011;
|
||||
const STICKY_DECIMALS = [0.25, 0.33, 0.5, 0.66, 0.75];
|
||||
const MAX_FRACTION_LENGTH = 4; // Permit 1/64 but not 1/100
|
||||
|
||||
export const formatNumberToFraction = (number: number) => {
|
||||
const sign = number >= 0 ? '+' : '-';
|
||||
|
||||
let decimal = (1 - Math.abs(number % 1)) > STICKY_THRESHOLD
|
||||
let decimal = (1 - Math.abs(number % 1)) > FRACTION_TOLERANCE
|
||||
? number % 1
|
||||
: 0;
|
||||
if (decimal !== 0) {
|
||||
for (const stickyDecimal of STICKY_DECIMALS) {
|
||||
if (Math.abs(Math.abs(decimal) - stickyDecimal) < STICKY_THRESHOLD) {
|
||||
if (Math.abs(Math.abs(decimal) - stickyDecimal) < FRACTION_TOLERANCE) {
|
||||
decimal = decimal < 0 ? -stickyDecimal : stickyDecimal;
|
||||
break;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user