Joe Attardi said:
If it is untrue, then why do the two examples come out with different
values?
Because 498 (aka. 4.98e2) can be represented exactly in the
representation used by Javascript's number type, but 4.98 cannot.
When you write 498 or 4.98e2 you get exactly that value.
The literal "4.98" does not give exactly the value 4.98, but rather
the representable value that is closest to that number. There is a
difference. When you then multiply by 100, the difference is also
multiplied, making it even more visible.
So what can I do to properly show the sum of an addition?
More importantly, how can you ensure that each operand of the
addition is exactly the number you expect? Generally, you can't.
The point of trying to use the scientific notation is to do what I
think is called scaled integer arithmetic? That is, 4.98 + 0.2 becomes
498 + 20, then the addition is integer addition, then the result is
divided back down for the correct result.
I don't know the name, but the approach is sound (as long as you
don't get results so big that they loose precission, i.e., something
that cannot be represented with 53 bits preission).
If using multiplication and division to move the decimal point won't
work, due to the floating point inaccuracies, what about (I know this
sounds messy) converting them to strings, counting the decimal places
in the string, removing the decimal point from the string, convert back
to numbers, perform the calculations, and merely insert a decimal point
in the string of the result?
Workable. You could also start out with two integer literals, one
for the number without the decimal point and one the position of
the point. Harder to read, but saves parsing the string.
Or you could create your own decimal number representation. Something
like:
---
function Dec(n,mag) {
this.n = Math.floor(n);
this.mag = Math.floor(mag);
}
Dec.prototype.add = function add(dec) {
if (this.mag < dec.mag) {
return dec.add(this);
}
var diff = this.mag - dec.mag;
return new Dec(this.n + Math.pow(10,diff) * dec.n, this.mag);
};
Dec.prototype.mult = function mult(dec) {
return new Dec(this.n * dec.n, this.mag + dec.mag);
};
Dec.prototype.toString = function toString() {
var n = this.n;
var mag = this.mag;
var res = [];
var sign = "";
if (n < 0) {
n = -n;
sign = "-";
}
while(mag > 0) {
res.push("0");
mag--;
}
while(n > 0) {
res.push(String(n%10));
n = Math.floor(n / 10);
mag++;
if (mag == 0) {
res.push(".");
}
}
while(mag < 0) {
res.push("0");
mag ++;
if (mag == 0) {
res.push(".");
}
}
res.push(sign);
return res.reverse().join("");
};
var d1 = new Dec(5); // 5.0
var d2 = new Dec(5,-1); // 0.5
var d3 = new Dec(5,1); //50.0
alert([d1.mult(d2),
d1.mult(d3),
d3.mult(d3),
d2.mult(d2)]); // 2.5,250,2500,.25