473,241 Members | 1,472 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,241 software developers and data experts.

Scientific notation - no rounding errors?

Hi all,

Math is not my strongest area so forgive me if I use some of the wrong
terminology.
It seems that scientific notation is immune to rounding errors. For
example:

(4.98 * 100) + 5.51 // returns 503.51000000000005, rounding error!
4.98e2 + 5.51 // returns 503.51, correct!

Why are scientific notation numbers not affected? And if this is true,
does this mean that scientific notation would be safe to use in a
floating-point addition function?

For example, 4.98 + 0.2, which comes out to 5.180000000000001
(incorrect!), would become (498e2 + 0.2e2) / 1e2, which comes out to
5.18 (correct!)

Any insight would be appreciated...

--
Joe

May 16 '06 #1
9 6576
Joe Attardi wrote on 16 mei 2006 in comp.lang.javascript:
Math is not my strongest area so forgive me if I use some of the wrong
terminology.
It seems that scientific notation is immune to rounding errors. For
example:

(4.98 * 100) + 5.51 // returns 503.51000000000005, rounding error!
4.98e2 + 5.51 // returns 503.51, correct!

Why are scientific notation numbers not affected?
Wrong, it is untrue.
And if this is true,
does this mean that scientific notation would be safe to use in a
floating-point addition function?
Unanswerable.
For example, 4.98 + 0.2, which comes out to 5.180000000000001
(incorrect!), would become (498e2 + 0.2e2) / 1e2, which comes out to
5.18 (correct!)
Only a single negative example can prove a point [to be incorrect],
while any finite number of positive examples is not enough for
correctness.

<http://en.wikipedia.org/wiki/Reductio_ad_absurdum>
Any insight would be appreciated...


Javascript arythmetic and storage use binary [=base 2] numbers.
All fraction numbers or results that are not exact floating point
binaries could introduce rounding errors, seen from a decimal world, or
through overflow of the mantissa.

So decimal 0.5 and 5e-1 are both exactly binary 0.1 and will make no
problems. 0.2 or 2e-1 [1/5] already gives me the creeps binary.

--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
May 16 '06 #2
Evertjan. wrote:
(4.98 * 100) + 5.51 // returns 503.51000000000005, rounding error!
4.98e2 + 5.51 // returns 503.51, correct!
Why are scientific notation numbers not affected?
Wrong, it is untrue.

If it is untrue, then why do the two examples come out with different
values?
Only a single negative example can prove a point [to be incorrect],
while any finite number of positive examples is not enough for
correctness. I realize that. I'm not trying to do a proof here, I'm just asking for
advice.
Javascript arythmetic and storage use binary [=base 2] numbers.
All fraction numbers or results that are not exact floating point
binaries could introduce rounding errors, seen from a decimal world, or
through overflow of the mantissa.

So what can I do to properly show the sum of an addition?
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.

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?

I know that sounds inefficient but it at least would get a proper
result, I think.

May 16 '06 #3
Rob
This problem is not limited to JavaSript. You may want to bone up on
the subject in a general cs book. There are a number of solutions to
handle rounding errors and I'm sure I don't know half of them. Your
solution of scaling the number, truncating to an integer and then
scaling back is one. The truncation hides the round off error.

The best solution is to format the numbers to show only the number of
significant digits your application requires. This hides the rounding
errors. It's up to you to design your application so that these errors
do not accumulate until a noticeable error occurs. If you use a
spreadsheet, these same factors apply. They just don't show you all the
digits by default. That's how the errors are hidden in a spreadsheet.

Rob:-]

May 16 '06 #4

Joe Attardi wrote:
Hi all,

Math is not my strongest area so forgive me if I use some of the wrong
terminology.
It seems that scientific notation is immune to rounding errors. For
example:

(4.98 * 100) + 5.51 // returns 503.51000000000005, rounding error!
4.98e2 + 5.51 // returns 503.51, correct!

Why are scientific notation numbers not affected? And if this is true,
does this mean that scientific notation would be safe to use in a
floating-point addition function?

For example, 4.98 + 0.2, which comes out to 5.180000000000001
(incorrect!), would become (498e2 + 0.2e2) / 1e2, which comes out to
5.18 (correct!)

Any insight would be appreciated...


Modern computers use number systems based on 2 or powers thereof such
as 2(binary), 4, 8(octal), 16(hex), 32, 64, 128 and so on. Most western
math is on a base 10 system. Anytime you convert from one number system
to another, there are going to be some errors introduced, as non-exact
numbers result in some cases. If you use decimals and allow division,
this ensures some numbers can not be represented exactly in some
systems. Consider that in the ordinary base 10 number system, division
of 1 by 3 gives a decimal number .33333 to infinity that can not be
written exactly.

The reason for the scientific number system is that some huge and very
small numbers are often used, and you do not want to have to write a
lot of leading or trailing zeros to do calculations. Some scientifc
calculations, if not very carefully programmed, will cause underflows
or overflows even if the computer can handle exp(100).

The 'funny" roundoffs have been with computing for well over 50 years
since digital computers based on a binary system were introduced, and
methods for handling this have been around just as long. People that
did money calculations soon started using cents rather than dollars in
the US so that fractions were avoided in additions and subtractions so
that "funny" numbers such as $1.00000001 would not disturb the bean
counters. In fact IBM had two different programs systems that were
widely used. Fortran was used for scientific calculations, and Cobal
was used for money calculations.

May 16 '06 #5
Rob
Here's a nice set of JavaScript techniques to deal with the problem:

http://www.mredkj.com/javascript/numberFormat.html

Or for a more rigorous treatment of the subject:

http://docs.sun.com/source/806-3568/ncg_goldberg.html

May 16 '06 #6
Rob
var num = 10;
var result = num.toFixed(2); // result will equal 10.00

num = 930.9805;
result = num.toFixed(3); // result will equal 930.981

num = 500.2349;
result = num.toPrecision(4); // result will equal 500.2

num = 5000.2349;
result = num.toPrecision(4); // result will equal 5000

num = 555.55;
result = num.toPrecision(2); // result will equal 5.6e+2

May 16 '06 #7
Rob wrote:
The best solution is to format the numbers to show only the number of
significant digits your application requires.


I basically need to compare a maximum to a computed total. The maximum
isn't known until runtime. So, to get the number of decimal places I
need, I could just count the number of decimal places in the maximum
and round the computed total to that many places?

May 16 '06 #8
"Joe Attardi" <ja******@gmail.com> writes:
Evertjan. wrote:
> (4.98 * 100) + 5.51 // returns 503.51000000000005, rounding error!
> 4.98e2 + 5.51 // returns 503.51, correct!
> Why are scientific notation numbers not affected?
Wrong, it is untrue.

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

---
Div and mod are the harder ones. You must still beware of overflow.

Good luck
/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
May 16 '06 #9
JRS: In article <11**********************@j33g2000cwa.googlegroups .com>
, dated Tue, 16 May 2006 10:16:56 remote, seen in
news:comp.lang.javascript, Joe Attardi <ja******@gmail.com> posted :
Math is not my strongest area so forgive me if I use some of the wrong
terminology.
It seems that scientific notation is immune to rounding errors. For
example:

(4.98 * 100) + 5.51 // returns 503.51000000000005, rounding error!
4.98e2 + 5.51 // returns 503.51, correct!
But that is a simpler calculation, one operation instead of two.
4.98*100 does not show 498.

Why are scientific notation numbers not affected? And if this is true,
does this mean that scientific notation would be safe to use in a
floating-point addition function?

For example, 4.98 + 0.2, which comes out to 5.180000000000001
(incorrect!), would become (498e2 + 0.2e2) / 1e2, which comes out to
5.18 (correct!)
It does not come out to 5.18, since a Number, being an IEEE Double,
cannot represent 5.18 exactly. However, conversion to String, for
output, would give something so close to 5.18 that 5.18 would be shown.

Now 5, being an integer no bigger than 2^53, is held exactly;
and 5.18-5 gives 0.17999999999999971
and (5.18-5)*100-18 gives -2.842170943040401e-14

A value exact in cents but handled as euros.cents will generally be
represented inexactly, and arithmetic will generally introduce further
error. But if the work is done in cents, it will be done without error.

I think an exact number of cents divided by 100 and converted to String
will be shown as you would wish, except for suppression of trailing
zeroes; it would be better to convert the integer to String and insert
the decimal point by character manipulation (e.g. RegExp .replace).

Note that multiplication by 0.01 gives inexact results, since 0.01
cannot be held exactly -
try for (J=0; J<1111; J++) document.writeln(J / 100, '<br>')
and for (J=0; J<1111; J++) document.writeln(J * 0.01, '<br>')

Any insight would be appreciated...


Read the newsgroup FAQ, sections 4.7, 4.6; read <URL:http://www.merlyn.
demon.co.uk/js-maths.htm> and follow links therein.

--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
<URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
<URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
May 16 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Woodster | last post by:
I am using the std::setprecision function to format variables of type double in a string however I am unsure how to stop this appearing in scientific notation. For example std::stringstream...
1
by: masoud bayan | last post by:
I have some values in type of double such 0.00009 , 0.0000007, when I want to show them in a text box and convert them to string they are changed to scientific notation while I want to show them as...
1
by: Nick | last post by:
Well, the project I am working on has now come to a screeching halt! I have been developing a program that heavily utilizes ADO.NET record sets. To generate reports, I convert the recordset to XML,...
0
by: Greg | last post by:
I am working on an application that requires working with numbers in scientific notation. I am using SqlServer as the database and I have created strongly typed data adapters and datasets. The...
7
by: Dustan | last post by:
How can I get a number into scientific notation? I have a preference for the format '1 E 50' (as an example), but if it's well known, it works.
2
by: Ryan Liu | last post by:
In C#, for a large float (9 digitals), how can I disable Scientific notation. When it auto convert to Scientific notation, I lost accuracy. Thanks a lot! Ryan
2
by: rSmoke | last post by:
I have a DataSet that contains a table with about 6 columns of high accuracy decimal values. When I try to write out the DataSet using the WriteXML() function the XML is written fine, but the...
7
by: grinder | last post by:
I have a program that fits a line to data points. The question is: can 'C' understand scientific notation (as below) , and if not what can i do to make it work.. 0.000 0.3231E+02 0.0000E+00 ...
2
by: Greg | last post by:
I am working on an application that requires working with numbers in scientific notation. I am using SqlServer as the database and I have created strongly typed data adapters and datasets. The...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.