cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Choose Language Hide Translation Bar
0 Kudos

Add possibility to round to even (banker's rounding) (or at least add teaching script to demonstrate the effect)

Add function to round to even / preference to change default rounding used by JMP (to my understanding both Python and R follow IEEE 754 and round to even by default). Also add Teaching Script to demonstrate the effect of rounding to even vs rounding to nearest. To my understanding round-to-even is the default behaviour for example in IEEE 754 - Rounding Rules (wikipedia.org)  Rounding to nearest should reduce bias when calculating aggregated statistics such as sum and mean from rounded values.

 

Below is example script (might not be the best demonstration...):

Names Default To Here(1);
// https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules
// https://blogs.sas.com/content/iml/2019/11/11/round-to-even.html
// https://stackoverflow.com/questions/311696/why-does-net-use-bankers-rounding-as-default

row_count = 400;
dt = New Table("Bankers_demo", Add Rows(row_count), New Column("TrueValue", Numeric, Continuous, Formula(0.25 * (Row() - 100))));

dt << New Column("RoundToNearest", Numeric, Continuous, Formula(Round(:TrueValue, 0)));
dt << New Column("RoundToEven",
	Numeric,
	Continuous,
	Formula(
		l = Words(Char(:TrueValue), ".");
		If(N Items(l) == 1,
			:TrueValue,
			If(l[2] == "5",
				If(Modulo(Num(l[1]), 2),
					Ceiling(:TrueValue),
					Floor(:TrueValue)
				),
				Round(:TrueValue, 0)
			)
		);
	)
);

dt << New Column("TrueSum", Numeric, Continuous, Formula(Col Cumulative Sum(:TrueValue)));
dt << New Column("NearestSum", Numeric, Continuous, Formula(Col Cumulative Sum(:RoundToNearest)));
dt << New Column("EvenSum", Numeric, Continuous, Formula(Col Cumulative Sum(:RoundToEven)));
dt << New Column("ErrorNearest", Numeric, Continuous, Formula(Abs(:TrueSum - :NearestSum)));
dt << New Column("ErrorEven", Numeric, Continuous, Formula(Abs(:TrueSum - :EvenSum)));

dt << New Column("TrueAvg", Numeric, Continuous, Formula(:TrueSum / Row()));
dt << New Column("NearestAvg", Numeric, Continuous, Formula(:NearestSum / Row()));
dt << New Column("EvenAvg", Numeric, Continuous, Formula(:EvenSum / Row()));


nw = New Window("Rounding",
	H List Box(
		Panel Box("Actions",
			Button Box("Add Row", dt << Add Rows(1, At End)),
			Button Box("Add 10 Rows", dt << Add Rows(10, At End)),
			Button Box("Add 100 Rows", dt << Add Rows(100, At End)),
			Button Box("Add 1000 Rows", dt << Add Rows(1000, At End))
		),
		gb = dt << Graph Builder(
			Size(528, 456),
			Show Control Panel(0),
			Variables(X(:TrueValue), Y(:ErrorNearest, Position(1)), Y(:ErrorEven, Position(1))),
			Elements(Points(X, Y(1), Y(2), Y(3), Legend(3)), Line(X, Y(1), Y(2), Y(3), Legend(5))),
			Local Data Filter(Add Filter(columns(:TrueValue))),
			SendToReport(
				Dispatch(
					{},
					"400",
					ScaleBox,
					{Legend Model(
						3,
						Base(0, 0, 0, Item ID("TrueSum", 1)),
						Base(1, 0, 0, Item ID("NearestSum", 1)),
						Base(2, 0, 0, Item ID("EvenSum", 1))
					)}
				)
			)
		),
		Tabulate(
			Show Control Panel(0),
			Add Table(Column Table(Statistics(Sum, Mean)), Row Table(Analysis Columns(:TrueValue, :RoundToNearest, :RoundToEven)))
		)
	),
	<< On Close(Try(Close(dt, No Save)))
);

 

 

1 Comment
SamGardner
Staff

Thanks for the detailed description.  We may take this under consideration for a future release.