Flash Website Builder- Trendy Site Builder is a Flash Site Building tool that helps users build stunning websites. Check Out Custom Custom Logo Design by LogoBee. Website Design and Free Logo Templates available.
 CodingForums.com Math Confusion

Before you post, read our: Rules & Posting Guidelines

Enjoy an ad free experience by logging in. Not a member yet? Register.
 09-09-2013, 12:36 AM PM User | #1 Md8^h2nx New to the CF scene   Join Date: Nov 2012 Posts: 7 Thanks: 4 Thanked 0 Times in 0 Posts Math Confusion How come in javascript 9.9 + 4.2 = 14.100000000000001
 09-09-2013, 12:41 AM PM User | #2 joesimmons New Coder   Join Date: Aug 2013 Posts: 50 Thanks: 0 Thanked 11 Times in 11 Posts Because all JS numbers are actually 64-bit floating point numbers. More info here: http://stackoverflow.com/questions/5...nt-math-broken There are workarounds, like this, for example: Code: ```function add(one, two) { return ( (one * 10) + (two * 10) ) / 10; } add(9.9, 4.2); // 14.1```
 09-09-2013, 12:46 AM PM User | #3 jmrker Senior Coder     Join Date: Aug 2006 Location: FL Posts: 2,935 Thanks: 36 Thanked 477 Times in 471 Posts Because of the accuracy of your computer math chip. Try... Code: `alert((9.9 + 4.2).toFixed(1))` Last edited by jmrker; 09-09-2013 at 12:48 AM.. Reason: types too slow.....
 09-09-2013, 08:30 AM PM User | #4 Philip M Supreme Master coder!     Join Date: Jun 2002 Location: London, England Posts: 17,475 Thanks: 200 Thanked 2,470 Times in 2,448 Posts .toFixed() cannot always be relied upon. alert (Math.round(0.49999999999999992).toFixed(2)) // results in 1.00 If you need an exact answer to a set number of decimal places then shift the decimal point in all your numbers that many places to the right to make integers before doing the calculation and then shift it back after the calculation. For example with currencies that use two decimal places you should always multiply them all by 100 at the start and divide by 100 at the end or the answer might not be exact. That is OK for addition, but for multiplication you need to divide by the multipliers squared Code: `````` __________________ All the code given in this post has been tested and is intended to address the question asked. Unless stated otherwise it is not just a demonstration. Last edited by Philip M; 09-09-2013 at 08:52 AM..
09-09-2013, 11:05 PM   PM User | #5
jmrker
Senior Coder

Join Date: Aug 2006
Location: FL
Posts: 2,935
Thanks: 36
Thanked 477 Times in 471 Posts

Quote:
 Originally Posted by Philip M .toFixed() cannot always be relied upon. alert (Math.round(0.49999999999999992).toFixed(2)) // results in 1.00
Why use Math.round?

Code:
`alert (0.49999999999999992.toFixed(2)) // results in 0.50`

09-10-2013, 12:08 AM   PM User | #6
Arbitrator
Senior Coder

Join Date: Mar 2006
Location: Splendora, Texas, United States of America
Posts: 3,139
Thanks: 11
Thanked 242 Times in 238 Posts
Quote:
 Originally Posted by jmrker Try... Code: `alert((9.9 + 4.2).toFixed(1))`
I'd add that this produces a string. If a number is desired, then one can explicitly convert it back to a number with:

Code:
`Number((9.9 + 4.2).toFixed(1));`
Quote:
 Originally Posted by Philip M .toFixed() cannot always be relied upon. alert (Math.round(0.49999999999999992).toFixed(2)) // results in 1.00
Interesting problem. Seems more like a flaw in `Math.round` than `toFixed` though. After rounding, you'll have either [0 or 1. `toFixed` returns the expected values (0.00 and 1.00) in both cases.
__________________
For every complex problem, there is an answer that is clear, simple, and wrong.

09-10-2013, 12:25 AM   PM User | #7
Old Pedant
Supreme Master coder!

Join Date: Feb 2009
Posts: 24,949
Thanks: 75
Thanked 4,307 Times in 4,274 Posts
Quote:
 Originally Posted by Arbitrator I'd add that this produces a string. If a number is desired, then one can explicitly convert it back to a number with: Code: `Number((9.9 + 4.2).toFixed(1));`
But one must remember that even *THAT* number is *NOT EXACTLY* 14.1.

No decimal tenth (0.1, 0.2, 0.3, etc.) except 0.5 can be expressed exactly in IEEE floating point (the number type used in all modern CPUs).

Remember, in binary floating point (which IEEE floating point uses), each bit to the right of the decimal point represents a NEGATIVE POWER OF 2.

So, in binary, 0.110101 is 2^-1 + 2^-2 + 2^-4 + 2^-6
which is 0.5 + 0.25 + 0.0625 + 0.015625
and even thought IEEE floating point extends those negative powers of 2 out to 53 binary digits, you simply can *NOT* represent 0.1, 0.2, etc., EXACTLY as the sum of such values, out to any number of binary digits.

Here's a little demo to show you how close you can get but it's still not 0.1:
Code:
```<script>
var s = 0;
var b = "0.";
for ( var i = 1; i < 60; ++i )
{
var p2 = Math.pow(2,-i);
if ( s + p2 < 0.1 )
{
b += "1";
s += p2;
document.write( "2^-" + i + " is " + p2 + ", sum is " + s + "<br/>");
} else {
b += "0";
}
}
document.write( "Binary notation: " + b )
</script>```
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.

Last edited by Old Pedant; 09-10-2013 at 12:28 AM..

 Users who have thanked Old Pedant for this post: Arbitrator (09-10-2013)
09-10-2013, 04:07 AM   PM User | #8
Arbitrator
Senior Coder

Join Date: Mar 2006
Location: Splendora, Texas, United States of America
Posts: 3,139
Thanks: 11
Thanked 242 Times in 238 Posts
Quote:
 Originally Posted by Old Pedant But one must remember that even *THAT* number is *NOT EXACTLY* 14.1. No decimal tenth (0.1, 0.2, 0.3, etc.) except 0.5 can be expressed exactly in IEEE floating point (the number type used in all modern CPUs). Remember, in binary floating point (which IEEE floating point uses), each bit to the right of the decimal point represents a NEGATIVE POWER OF 2.
That begs the question as to why every number isn't just offset (in JavaScript) so that it's an integer for the purpose of calculations... Bad performance?

So I guess the best solution is to determine how many decimal places are desired and use something like joesimmon's idea of implementing an add function... though I'd do it a bit differently:

Code:
```Math.add = function () {
var sum = 0;
var argumentsIndex = 0;
while (argumentsIndex < arguments.length) {
sum += arguments[argumentsIndex] * 1000; // thousandths offset
argumentsIndex += 1;
}
return sum / 1000; // reversed thousandths offset
};
__________________
For every complex problem, there is an answer that is clear, simple, and wrong.

09-10-2013, 04:21 AM   PM User | #9
felgall
Master Coder

Join Date: Sep 2005
Location: Sydney, Australia
Posts: 6,092
Thanks: 0
Thanked 579 Times in 569 Posts
Quote:
 Originally Posted by Arbitrator That begs the question as to why every number isn't just offset (in JavaScript) so that it's an integer for the purpose of calculations
Because for most floating point numbers that would give meaningless results.

Consider what would happen if 3e100 were to be converted from a floating point number to an integer before being used in a calculation - it would overflow the available memory in trying to add all the zeros. Or imagine if you were multiplying by 1e-20.

Also the values that the calculations are performed on ARE integers - being the nearest binary equivalent of the number with the number of decimal places to offset the result being stored separately (the 300 and -20 in the above examples).

When you use floating point numbers in any programming language it is assumed that you only need the answer to be accurate to a few decimal places (approximately 15 in the case of JavaScript).

Only when you are using small integers do you expect computer calculations to be completely accurate after the decimal to binary to decimal conversions because only there do the decimal numbers have exact binary equivalents.
__________________
Stephen
Learn Modern JavaScript - http://javascriptexample.net/
Helping others to solve their computer problem at http://www.felgall.com/

Beginners need to advise whether they want to learn "Latin" JavaScript for Netscape 3 or "Italian" JavaScript for modern browsers.

 Users who have thanked felgall for this post: Arbitrator (09-10-2013)
09-10-2013, 04:59 AM   PM User | #10
Arbitrator
Senior Coder

Join Date: Mar 2006
Location: Splendora, Texas, United States of America
Posts: 3,139
Thanks: 11
Thanked 242 Times in 238 Posts
Quote:
 Originally Posted by felgall When you use floating point numbers in any programming language it is assumed that you only need the answer to be accurate to a few decimal places (approximately 15 in the case of JavaScript).
It's not exactly "assumed" if you can't accurately add two numbers with a tenths digit without creating an intermediary function.

Sounds like they should have come up with two types: IEEEFloatingPointNumber—what we have now—and AccurateNumber, which is limited to and accurate within that 15-digit range and what the average Joe would use with mathematical operations.
__________________
For every complex problem, there is an answer that is clear, simple, and wrong.

09-10-2013, 09:14 AM   PM User | #11
felgall
Master Coder

Join Date: Sep 2005
Location: Sydney, Australia
Posts: 6,092
Thanks: 0
Thanked 579 Times in 569 Posts
Quote:
 Originally Posted by Arbitrator Sounds like they should have come up with two types: IEEEFloatingPointNumber—what we have now—and AccurateNumber, which is limited to and accurate within that 15-digit range and what the average Joe would use with mathematical operations.
They have - in JavaScript numbers without an e or decimal point are limited to and accurate within that 15 digit range. If the number contains a decimal point or an e then it is an IEEEFloatingPointNumber.

Anyway 4.2 cannot be accurately entered within the 15 digits available. Other numbers such as 4.25 and 4.0078125 and 4.000003814697265625 and 4.0000000000582076609134674072265625 which can be held exactly within the 15 available digits do not cause unexpected results provided they are used with other numbers that can also be exactly entered.
__________________
Stephen
Learn Modern JavaScript - http://javascriptexample.net/
Helping others to solve their computer problem at http://www.felgall.com/

Beginners need to advise whether they want to learn "Latin" JavaScript for Netscape 3 or "Italian" JavaScript for modern browsers.

Last edited by felgall; 09-10-2013 at 09:22 PM..

09-10-2013, 08:56 PM   PM User | #12
Old Pedant
Supreme Master coder!

Join Date: Feb 2009
Posts: 24,949
Thanks: 75
Thanked 4,307 Times in 4,274 Posts
Quote:
 Originally Posted by Arbitrator It's not exactly "assumed" if you can't accurately add two numbers with a tenths digit without creating an intermediary function. Sounds like they should have come up with two types: IEEEFloatingPointNumber—what we have now—and AccurateNumber, which is limited to and accurate within that 15-digit range and what the average Joe would use with mathematical operations.
They have, in other languages. It's called DECIMAL numbers. For example, MySQL (and SQL Server) support the DECIMAL datatype. You specify a numbers as (example) `DECIMAL(20,4)` which means it can hold 20 digits, 4 of which are to the right of the decimal point.

By the by, all of the Microsoft .NET languages *can* have this capability, too. It's built into the .NET framework. VB.NET and C# have the DECIMAL data type as a syntactical part of the language and C++ (and other languages) can use it via an extended library.

But don't think the DECIMAL type solves everything. Now how do you represent 1/3 exactly???? If you have a variable declared as DECIMAL(20,4) and assign the value 1/3 to it, you will see it as 0.3333, which looks fine. But now multiply it by 3 and you get 0.9999, whereas we all know that 3 * 1/3 is exactly 1. Right?

There is no way in *ANY* notation, in *ANY* base of numbers, to EXACTLY represent all possible fractions. Suppose we used BASE-3 numbers. So then 1/3 would be represented as 0.100000, exactly. But *NOW* there is no way to represent 1/2 exactly!

Pardon me, but people who expect exact numerical results from any computer-based system are akin to those ancient alchemists who thought you could turn lead into gold.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.

 09-10-2013, 09:05 PM PM User | #13 Old Pedant Supreme Master coder!     Join Date: Feb 2009 Posts: 24,949 Thanks: 75 Thanked 4,307 Times in 4,274 Posts As a comment on my own personal history... I had the opportunity four times in my career to create floating point number systems in software. This was long before floating point hardware was standard (in fact, the hardware I worked on didn't have ANY multiply or divide built in!) and even before the IEEE adopted the current standards. Two of those four times (for BASIC languages we produced for Atari 8-bit computers) I opted to use DECIMAL FLOATING POINT. And just for the reasons that this thread has been discussing: Human beings, trained to use decimal, are just more comfortable when they can add 0.1 to itself 10 times and come up with *exactly* 1.00 (and so on). And I think many of the people who used those two languages appreciated my choice, especially those who wrote programs dealing with money. But let's face it: Decimal floating point, even if built into hardware, is much much slower for computers than is binary floating point. And, in the end, it still doesn't solve the problem of representing 1/3 (or 1/7 or 1/11 or...) *exactly*. So learn to live with binary floating point. It's here to stay. __________________ An optimist sees the glass as half full. A pessimist sees the glass as half empty. A realist drinks it no matter how much there is.

 Bookmarks

 Thread Tools Rate This Thread Rate This Thread: 5 : Excellent 4 : Good 3 : Average 2 : Bad 1 : Terrible

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is Off Forum Rules
 Forum Jump User Control Panel Private Messages Subscriptions Who's Online Search Forums Forums Home :: Client side development     JavaScript programming         DOM and JSON scripting         Ajax and Design         JavaScript frameworks         Post a JavaScript     HTML & CSS     XML     Flash & ActionScript         Adobe Flex     Graphics and Multimedia discussions     General web building         Site reviews         Building for mobile devices :: Server side development     Apache configuration     Perl/ CGI     PHP         Post a PHP snippet     MySQL         Other Databases     Ruby & Ruby On Rails     ASP     ASP.NET     Java and JSP     Other server side languages/ issues         ColdFusion         Python :: Computing & Sciences     Computer Programming     Computer/PC discussions     Geek News and Humour Web Projects and Services Marketplace     Web Projects         Small projects (quick fixes and changes)         Medium projects (new script, new features, etc)         Large Projects (new web application, complex features etc)         Unknown sized projects (request quote)         Vacant job positions         Looking for work/ for hire         Project collaboration/ partnership         Paid work offers and requests (Now CLOSED)     Career, job, and business ideas or advice     Domains, Sites, and Designs for sale         Domains for sale         Websites for sale         Design templates and graphics for sale :: Other forums     Member Offers     Forum feedback and announcements

All times are GMT +1. The time now is 08:22 AM.