Refine fraction formatting behavior
This commit is contained in:
parent
4e3d1dec08
commit
ae3770ae30
@ -12,23 +12,35 @@ describe('EXIF', () => {
|
||||
expect(formatExposureTime(1.5)).toBe('1.5s');
|
||||
});
|
||||
it('exposure compensation', () => {
|
||||
expect(formatExposureCompensation(1)).toBe('+1ev');
|
||||
expect(formatExposureCompensation(-1)).toBe('-1ev');
|
||||
expect(formatExposureCompensation(0)).toBe(undefined);
|
||||
expect(formatExposureCompensation(0.25)).toBe('+1/4ev');
|
||||
expect(formatExposureCompensation(0.33)).toBe('+1/3ev');
|
||||
expect(formatExposureCompensation(0.333)).toBe('+1/3ev');
|
||||
expect(formatExposureCompensation(-0.25)).toBe('-1/4ev');
|
||||
expect(formatExposureCompensation(-0.33)).toBe('-1/3ev');
|
||||
expect(formatExposureCompensation(-0.333)).toBe('-1/3ev');
|
||||
expect(formatExposureCompensation(0.5)).toBe('+1/2ev');
|
||||
expect(formatExposureCompensation(0.4998458896569944)).toBe('+1/2ev');
|
||||
expect(formatExposureCompensation(0.66)).toBe('+2/3ev');
|
||||
expect(formatExposureCompensation(0.67)).toBe('+2/3ev');
|
||||
expect(formatExposureCompensation(0.015625)).toBe('+1/64ev');
|
||||
expect(formatExposureCompensation(-0.015625)).toBe('-1/64ev');
|
||||
expect(formatExposureCompensation(1)).toBe('+1ev');
|
||||
expect(formatExposureCompensation(1.1)).toBe('+1 1/10ev');
|
||||
expect(formatExposureCompensation(-1.1)).toBe('-1 1/10ev');
|
||||
expect(formatExposureCompensation(1.7)).toBe('+1 7/10ev');
|
||||
expect(formatExposureCompensation(-1.7)).toBe('-1 7/10ev');
|
||||
expect(formatExposureCompensation(-1.33)).toBe('-1 1/3ev');
|
||||
expect(formatExposureCompensation(1.33)).toBe('+1 1/3ev');
|
||||
expect(formatExposureCompensation(1.333)).toBe('+1 1/3ev');
|
||||
expect(formatExposureCompensation(1.3333)).toBe('+1 1/3ev');
|
||||
expect(formatExposureCompensation(1.5)).toBe('+1 1/2ev');
|
||||
expect(formatExposureCompensation(2.5)).toBe('+2 1/2ev');
|
||||
expect(formatExposureCompensation(-2.5)).toBe('-2 1/2ev');
|
||||
expect(formatExposureCompensation(1.9960938)).toBe('+2ev');
|
||||
expect(formatExposureCompensation(-1.9960938)).toBe('-2ev');
|
||||
// Ignore long fractions
|
||||
expect(formatExposureCompensation(-0.119)).toBe('-0.12ev');
|
||||
expect(formatExposureCompensation(-0.112340989)).toBe('-0.11ev');
|
||||
|
||||
@ -14,10 +14,13 @@ const gcd = (a: number, b: number): number => {
|
||||
}
|
||||
};
|
||||
|
||||
const formatDecimalToFraction = (decimal: number) => {
|
||||
if (Math.abs(decimal - 0.33) < 0.011) {
|
||||
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) {
|
||||
return '1/3';
|
||||
} else if (Math.abs(decimal - 0.66) <= 0.011) {
|
||||
} else if (Math.abs(Math.abs(decimal) - 0.66) <= 0.011) {
|
||||
return '2/3';
|
||||
} else {
|
||||
const length = decimal.toString().length - 2;
|
||||
@ -34,22 +37,43 @@ 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; // 1/64 not 1/100
|
||||
|
||||
export const formatNumberToFraction = (number: number) => {
|
||||
const decimal = (1 - number % 1) > 0.01
|
||||
const sign = number >= 0 ? '+' : '-';
|
||||
|
||||
let decimal = (1 - Math.abs(number % 1)) > STICKY_THRESHOLD
|
||||
? number % 1
|
||||
: 0;
|
||||
const integer = Math.round(Math.abs(number - decimal));
|
||||
if (decimal !== 0) {
|
||||
for (const stickyDecimal of STICKY_DECIMALS) {
|
||||
if (Math.abs(Math.abs(decimal) - stickyDecimal) < STICKY_THRESHOLD) {
|
||||
decimal = decimal < 0 ? -stickyDecimal : stickyDecimal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let integer = Math.round(Math.abs(number - decimal));
|
||||
if (Math.abs(decimal) === 1) {
|
||||
decimal = 0;
|
||||
integer += 1;
|
||||
}
|
||||
|
||||
const fraction = decimal !== 0
|
||||
? formatDecimalToFraction(Math.abs(decimal))
|
||||
: '';
|
||||
const sign = number >= 0 ? '+' : '-';
|
||||
// Ensure fractions are not too long
|
||||
if (!fraction || fraction.length <= 4) {
|
||||
const whole = integer > 0
|
||||
|
||||
// Ensure fractions aren't too long
|
||||
if (!fraction || fraction.length <= MAX_FRACTION_LENGTH) {
|
||||
const integerString = integer > 0
|
||||
? fraction ? `${integer} ` : integer
|
||||
: fraction ? '' : '0';
|
||||
return `${sign}${whole}${fraction}`;
|
||||
return `${sign}${integerString}${fraction}`;
|
||||
} else {
|
||||
// console.log({ fraction });
|
||||
const decimalFormatted = decimal.toPrecision(2).replace(/^-*0+/, '');
|
||||
return `${sign}${integer}${decimalFormatted}`;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user