Skip to content

Commit

Permalink
feat: add reverse mechanism
Browse files Browse the repository at this point in the history
the original library contains a "reverse" mechanism, that influences
which element is being rounded next. added tests proving that it aligns
with the readme example and the examples from the "basic_difference" test.

contributes to #134
  • Loading branch information
boredland committed Feb 27, 2023
1 parent 28114b2 commit c643f4f
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 69 deletions.
111 changes: 43 additions & 68 deletions src/safeRound.test.ts
Original file line number Diff line number Diff line change
@@ -1,117 +1,92 @@
import { roundToPlaces, safeRound, sumUp } from './safeRound';
import { roundToPlaces, safeRound, sumUp } from "./safeRound";

describe('round', () => {
test('round to no places (int)', () => {
describe("round", () => {
test("round to no places (int)", () => {
const result = roundToPlaces(1.6, 0);
expect(result).toBe(2);
});

test('round to two places (int)', () => {
test("round to two places (int)", () => {
const result = roundToPlaces(1.667, 2);
expect(result).toBe(1.67);
});
})
});

describe('sum', () => {
test('sum up and round (int)', () => {
describe("sum", () => {
test("sum up and round (int)", () => {
const result = sumUp([1.5, 1.66, 0.177]);
expect(result).toBe(3);
});

test('sum up and round to decimal', () => {
test("sum up and round to decimal", () => {
const result = sumUp([1.5, 1.66, 0.177], 2);
expect(result).toBe(3.34);
});

test('sum up positive and negative', () => {
test("sum up positive and negative", () => {
const result = sumUp([2, -2, -1]);
expect(result).toBe(-1);
});
})
});

describe('safe round', () => {
describe("safe round", () => {
const fixture = [4.0001, 3.2345, 3.2321, 6.4523, 5.3453, 7.3422];

test('to 0 places (int)', () => {
test("to 0 places (int)", () => {
const result = safeRound(fixture, 0);
expect(result).toEqual([
5,
3,
4,
6,
5,
7,
]);
expect(result).toEqual([4, 3, 3, 7, 6, 7]);
expect(sumUp(result)).toBe(sumUp(fixture));
});

test('rounds to second place (decimal)', () => {
test("rounds to second place (decimal)", () => {
const result = safeRound(fixture, 2);
expect(result).toEqual([
4,
3.23,
3.23,
6.45,
5.36,
7.34,
]);
expect(result).toEqual([4, 3.24, 3.23, 6.45, 5.35, 7.34]);
expect(sumUp(result)).toBe(sumUp(fixture));
});

test('rounds negative (decimal)', () => {
const negativeFixture = fixture.map(v => v * -1);
test("rounds negative (decimal)", () => {
const negativeFixture = fixture.map((v) => v * -1);
const result = safeRound(negativeFixture, 2);
expect(result).toEqual([
-4,
-3.24,
-3.23,
-6.45,
-5.35,
-7.34,
]);
expect(result).toEqual([-4, -3.24, -3.23, -6.45, -5.35, -7.34]);
expect(sumUp(result)).toBe(sumUp(negativeFixture));
});

test('rounds huge (int)', () => {
const hugeFixture = fixture.map(v => v * 100000);
test("rounds huge (int)", () => {
const hugeFixture = fixture.map((v) => v * 100000);
const result = safeRound(hugeFixture, 0);
expect(result).toEqual([400010, 323450, 323210, 645230, 534530, 734220]);
expect(sumUp(result)).toBe(sumUp(hugeFixture));
});

test('returns empty on empty input', () => {
test("returns empty on empty input", () => {
const result = safeRound([], 5);
expect(result).toEqual([]);
});

test('rounds near zero', () => {
test("rounds near zero", () => {
const fixture = [
0.013245557004700679,
0.7268604797100215,
0.6155001637295456,
0.06875329582046738,
0.8387831576913838,
0.03243429881206358,
0.0023860988000495792,
0.41960946536150784,
0.675551119386058,
0.6409523907667709,
0.9659239729174308,
0.013245557004700679, 0.7268604797100215, 0.6155001637295456,
0.06875329582046738, 0.8387831576913838, 0.03243429881206358,
0.0023860988000495792, 0.41960946536150784, 0.675551119386058,
0.6409523907667709, 0.9659239729174308,
];
const result = safeRound(fixture);
expect(result).toEqual([
0,
1,
0,
0,
1,
0,
0,
0,
1,
1,
1,
]);
expect(result).toEqual([0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1]);
expect(sumUp(result)).toBe(sumUp(fixture));
});
})

test("readme example", () => {
const fixture = [60.19012964572332, 15.428802458406679, 24.381067895870007];
const out = [60, 16, 24];
const result = safeRound(fixture, 0);

expect(result).toEqual(out);
});

test("test_basic_difference", () => {
const out = [4.0, 3.24, 3.23, 6.45, 5.35, 7.34];
const result = safeRound(fixture, 2);

expect(result).toEqual(out);
})
});
6 changes: 5 additions & 1 deletion src/safeRound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,17 @@ export const safeRound = (values: number[], places = 0) => {

while (list.sum !== list.originalSum) {
const diff = roundToPlaces(list.originalSum - list.sum, places);

let reverse = true;
if (diff < 0) {
increment = -1 * _mininc(places);
reverse = false;
} else {
increment = _mininc(places);
reverse = true;
}
const tweaks = Math.floor(Math.abs(diff) / _mininc(places));
const items = list.items.sort((a,b) => a.diff - b.diff);
const items = list.items.sort((a,b) => reverse ? b.diff - a.diff : a.diff - b.diff);

[...items.slice(0, tweaks)].forEach((v, i) => {
items[i].add(increment);
Expand Down

0 comments on commit c643f4f

Please # to comment.