I'm developing an online game that uses deterministic physics, and it seems that trigonometric / transcendental functions can be implemented differently on different browsers, and give slightly different results. I need the results to be the exact same on every browser.
From all the testing I've done (Chrome, Firefox, Safari), it seems their answers are basically identical. Math.sin
and Math.cos
seem to give identical results on the latest versions of Chrome, Firefox, and Safari. Math.atan2
on the other-hand seems to give identical results on Chrome and Firefox, but the last (16th) digit differs by one on Safari.
This being the case, rather than implement my own versions of sin
, cos
, atan2
, would it be safe to do something like this?
function crossPlatformCos(x) {
const precision = 100000;
return Math.floor(Math.cos(x) * precision) / precision;
}
The logic being that it is extremely unlikely for a browser to differ by that many decimals. This approach basically rounds cos
down to 6 or so decimal places, instead of 16. And honestly, even if this only works for 99.99% of users, I'm fine with that.
I suppose my question is, does this sound reasonable? And would this work to ensure deterministic behavior for all the transcendental functions that may have slightly differing implementations on different browsers / platforms? If I don't need 16 digits of precision and am fine with 6, would this sort of logic ensure maximal determinism? Or is it still recommended to create my own versions of everything? By using something like this:
const tp = 1 / (2 * Math.PI);
function cos(x) {
const a = x * tp;
const b = a - (0.25 + Math.floor(a + 0.25));
const c = b * (16 * (Math.abs(b) - 0.5));
return c + 0.225 * c * (Math.abs(c) - 1.0);
}