Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Trying parseFloat, but acts like parseBloat 1

Status
Not open for further replies.

EdwardMartinIII

Technical User
Sep 17, 2002
1,655
US
I should be smarter than this. Really. But this is very weird

I am attempting to tally up a row of text fields. Very simple, right? I use parseFloat on each element.

The code in "Sample.js" is below:
Code:
function BigTally()
  {
    // tally each subtotal first
    document.MainForm.i1total.value=(parseFloat(document.MainForm.i1c1.value)+parseFloat(document.MainForm.i1c2.value)+parseFloat(document.MainForm.i1c3.value));
    // now sum the subtotals to the grand total.
    document.MainForm.GrandTotal.value=parseFloat(document.MainForm.i1total.value);
  }

All it does is add the contents of the three fields. This should be a no-brainer.

The HTML code is here:

Code:
<!DOCTYPE html 
     PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;
     &quot;[URL unfurl="true"]http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;>[/URL]

<html xmlns=&quot;[URL unfurl="true"]http://www.w3.org/1999/xhtml&quot;[/URL] xml:lang=&quot;en&quot; lang=&quot;en&quot;>
  <head>
    <meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=iso-8859-1&quot;></meta>
    <title>JavaScript Sample</title>
    <script src=&quot;Sample.js&quot; type=&quot;text/javascript&quot;></script>
  </head>
  <body>
    <form name=&quot;MainForm&quot; action=&quot;&quot;>
      <h3>Tally 'em up!</h3>
      <table border=&quot;1&quot;>
        <tr>
          <td>item 1 cost 1: <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i1c1&quot; id=&quot;i1c1&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
          <td>item 1 cost 2: <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i1c2&quot; id=&quot;i1c2&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
          <td>item 1 cost 3: <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i1c3&quot; id=&quot;i1c3&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
          <td><strong>item 1 Total:</strong> <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i1total&quot; id=&quot;i1total&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
        </tr>
        <tr>
          <td>item 2 cost 1: <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i2c1&quot; id=&quot;i2c1&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
          <td>item 2 cost 2: <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i2c2&quot; id=&quot;i2c2&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
          <td>item 2 cost 3: <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i2c3&quot; id=&quot;i2c3&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
          <td><strong>item 2 Total:</strong> <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i2total&quot; id=&quot;i2total&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
        </tr>
        <tr>
          <td>item 3 cost 1: <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i3c1&quot; id=&quot;i3c1&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
          <td>item 3 cost 2: <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i3c2&quot; id=&quot;i3c2&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
          <td>item 3 cost 3: <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i3c3&quot; id=&quot;i3c3&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
          <td><strong>item 3 Total:</strong> <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i3total&quot; id=&quot;i3total&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
        </tr>
        <tr>
          <td>item 4 cost 1: <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i4c1&quot; id=&quot;i4c1&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
          <td>item 4 cost 2: <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i4c2&quot; id=&quot;i4c2&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
          <td>item 4 cost 3: <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i4c3&quot; id=&quot;i4c3&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
          <td><strong>item 4 Total:</strong> <input type=&quot;text&quot; value=&quot;0&quot; name=&quot;i4total&quot; id=&quot;i4total&quot; size=&quot;5&quot; onblur=&quot;BigTally();return true;&quot;></input></td>
        </tr>
        <tr>
          <td colspan=&quot;4&quot; align=&quot;right&quot;><strong>Grand Total: </strong><input type=&quot;text&quot; value=&quot;0&quot; name=&quot;GrandTotal&quot; id=&quot;GrandTotal&quot;size=&quot;50&quot;></input></td>
        </tr>
      </table>
    </form>
  </body>
</html>

Now, the trouble occurs when I enter
Item 1 cost 1: 83
Item 1 cost 2 45.67

The item 1 total kicks out 128.67000000000002. The same thing happens when I reverse the arguments (even faulty addition is commutative, evidently). However, if I subtract 1 from either argument (82 instead of 83 or 44.67 instead of 45.67), the answer tallies out fine!

What the holy guacamole's goin' on?

Can anyone tell me what I might be doing wrong here?

Cheers,


[monkey] Edward [monkey]

&quot;Cut a hole in the door. Hang a flap. Criminy, why didn't I think of this earlier?!&quot; -- inventor of the cat door
 
This seems normal float behaviour. (The precision of scientific, floating point nunmburrs)

So the solution should be something like

x =(
(parseFloat(document.MainForm.i1c1.value)+parseFloat(document.MainForm.i1c2.value)+parseFloat(document.MainForm.i1c3.value));
) * 100 ;

x=parseInt(x) ;
document.MainForm.i1total.value = x /100. ;

or some such thing.

 
Hi, thanks for writing back.

Normal float behavior? For a Pentium, perhaps. [lol] (holy crap, this is an old computer -- what if it's one of those &quot;bad&quot; Pentiums? How would I know?)

I used two decimal places in my example only -- any solution should work on any small number of decimals.

And I've never encountered a programming situation where 83 + 45.67 equalled anything other than 128.67. Especially when 82 + 45.67 came out to 127.67. That's not &quot;normal&quot;, that's &quot;flat out incorrect&quot; and in a sphere of numbers that should be easy-peasy for any programming language laying claim to the ability to add floats.

Cheers,


[monkey] Edward [monkey]

&quot;Cut a hole in the door. Hang a flap. Criminy, why didn't I think of this earlier?!&quot; -- inventor of the cat door
 
I have a question for you... why do you have to say this..

document.MainForm.GrandTotal.value=parseFloat(document.MainForm.i1total.value);

Intead of just simply saying this...

document.MainForm.GrandTotal.value=document.MainForm.i1total.value);

I am no programmer.. just learning as I go along. The answer to the above question is more for me than you ..

Wish I could help ya

Brian
 
datatype conversion

everything in javascript is considered a string unless converted with the datatype functions.

that is unless specified and declared as
var int = 1

but everything that is passed as a parameter is a string and you can't add strings

____________________________________________________
The most important part of your thread is the subject line.
Make it clear and about the topic so we can find it later for reference. Please!! faq333-2924

onpnt2.gif
 
sdi's question is very valid since all form fields are read by javascript and form handlers as text anyway - why would you try to convert a value to a numeric datatype when writing to the form field?

Programming today is a race between software engineers striving to build better and bigger idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning. - Rick Cook
 
[ponder]
I was thinking along the lines of other tasks being perfomred to the value, but you are correct. it does seem like a un-needed use of conversion.

____________________________________________________
The most important part of your thread is the subject line.
Make it clear and about the topic so we can find it later for reference. Please!! faq333-2924

onpnt2.gif
 
Well I don't have the answer to the question why, all I know is that I have a shopping cart script that inhereted the same problem... The solution was to set the text box so that it would round the number.. Your right Edward it shouldn't do it... Wolf thanks for the interpretation of what I was asking.. Although when I looked closer at it, I realized we only had one part presented to us..

I think this is what was going on from how the table displays from the Html given...

sample.js

function BigTally()
{
// tally each subtotal first
document.MainForm.i1total.value=(parseFloat(document.MainForm.i1c1.value)+parseFloat(document.MainForm.i1c2.value)+parseFloat(document.MainForm.i1c3.value));
document.MainForm.i2total.value=(parseFloat(document.MainForm.i2c1.value)+parseFloat(document.MainForm.i2c2.value)+parseFloat(document.MainForm.i2c3.value));
document.MainForm.i3total.value=(parseFloat(document.MainForm.i3c1.value)+parseFloat(document.MainForm.i3c2.value)+parseFloat(document.MainForm.i3c3.value));
document.MainForm.i4total.value=(parseFloat(document.MainForm.i4c1.value)+parseFloat(document.MainForm.i4c2.value)+parseFloat(document.MainForm.i4c3.value));
// now sum the subtotals to the grand total.
document.MainForm.GrandTotal.value=parseFloat(document.MainForm.i1total.value)+parseFloat(document.MainForm.i2total.value)+parseFloat(document.MainForm.i3total.value)+parseFloat(document.MainForm.i4total.value);
}

 
sdi: I have a question for you... why do you have to say this..

Ah, because you're only seeing the simplified version of the problem.

If you look in the js listing, you'll see a comment about adding to the subtotals (I only do one for the example), and then the comment about adding the subtotals to create the GrandTotal.

But, from the example, even the SubTotal value is bogus, so there's not a lot of point in working out the Grand Total yet, is there? In the actual page, there's a bunch of pieces added together.

Now, the reason that I use parseFloat is that eventually (when you look at the HTML file, this is obvious), there's gonna be a buttload of adding going on. If I add &quot;100.25&quot; to &quot;45.56&quot;, I will get &quot;100.2545.56&quot; unless I parseFloat 'em.

Which brings me back to the very, very simple question -- what am I doing wrong such that I add two perfectly well-behaved decimals and get some spackle-nosed answer such as &quot;128.67000000000002&quot;?

AnanthaP suggested this was par for the course for a parseFloat, but it seems completely contrary to any other language implementation for a parseFloat. It's not as if I'm even doing a hairy computation -- this is simply addition. The only thing that makes these numbers interesting is that they pass across 128, which is half of 256, which is a power of two, blah-blah-blah. But it would be profoundly retarded to assume that JavaScript can't handle a float outside of the (-127 to 127) range.

Therefore, I must be doing something wrong. But what...?

Cheers,


[monkey] Edward [monkey]

&quot;Cut a hole in the door. Hang a flap. Criminy, why didn't I think of this earlier?!&quot; -- inventor of the cat door
 
&quot;I used two decimal places in my example only -- any solution should work on any small number of decimals.&quot;

Besides, why should I need code to correct what is a pathetic addition error? If such an easy solution is producing an incorrect example, it must be because I am using parseFloat incorrectly, or perhaps because parseFloat isn't the correct tool when adding two numbers. [lol]

Cheers,


[monkey] Edward [monkey]

&quot;Cut a hole in the door. Hang a flap. Criminy, why didn't I think of this earlier?!&quot; -- inventor of the cat door
 
Okay.

I'm at the home machine now, which is much too new to have float problems, and running it under Mozilla.

Add 100 and 100.66, the answer is 200.66
Add 100 and 100.67, the answer is 200.67000000000002
Add 100 and 100.68, the answer is 200.68

So, once again, a show of hands: who thinks this is what's supposed to happen...?

What the hell am I doing wrong, here?

Cheers,


[monkey] Edward [monkey]

&quot;Cut a hole in the door. Hang a flap. Criminy, why didn't I think of this earlier?!&quot; -- inventor of the cat door
 
Jeff,

I read through the PDF, but could find no indication that this is what is expected.

Okay, Every Single Time someone posts something to this or other fora, declaring &quot;Netscape has a bug!&quot; or &quot;Photoshop has a bug&quot;, I have assumed that they were simply experiencing a wetware problem and have always been proven correct in this assessment.

I approached this problem from the same direction -- smarter monkeys than I built this damn language, and this is a simple, fundamental operation. The idea that such a simple thing would produce such inaccuracy is -- dare I use the word -- inconceivable!

But then I found
and
(which both view it as a fixed 2-decimal problem)
and
and

I tried &quot;converting&quot; the number using the &quot;-0&quot; trick (without explicitly using parseFloat) and the same darn thing happened.

So, I'm going to go watch Richard Pryor's character steal millions of dollars from a comapny by slicing fractional pennies and think to myself &quot;How easy is THAT, using JavaScript?!&quot; unless someone convinces me that it's not a language bug (bad Sun, no biscuit!)

Cheers,


[monkey] Edward [monkey]

&quot;Cut a hole in the door. Hang a flap. Criminy, why didn't I think of this earlier?!&quot; -- inventor of the cat door
 
actually, Netscape wrote javascript, not Sun.

and it's probably still correct ;-)
see particularly the first article &quot;What Every Computer Scientist Should Know About Floating-Point Arithmetic&quot;
David Goldberg, ACM Computing Surveys, pp. 5-48, vol. 23#1, 1991

=========================================================
try { succeed(); } catch(E) { tryAgain(); }
-jeff
 
A fascinating article -- I've breezed through it and will read in depth later.

So, basically, even these trivial cases must be guarded against FP errors? Okay, as soon as a different language than JavaScript produces the same wonky results for the same (or similar) numbers, I'm going to assume that whoever wrote the FP routines for JavaScript didn't actually write sufficient catch.

I can understand this -- someone else has pointed out that my calculator takes a very long time to calculate 1^50000, which makes sense when you realize I dropped the ball programming in a catch for x = 1 or x = 0.

Annoying, however... Must be something from the Dimension of Pain.

Cheers,


[monkey] Edward [monkey]

&quot;Cut a hole in the door. Hang a flap. Criminy, why didn't I think of this earlier?!&quot; -- inventor of the cat door
 
Argh!

Okay, so, in order to do calculations of this sort in JavaScript, you basically have to force the decimal representation to not be treated as an actual Real value. Otherwise, you just can't trust 'em.

So, basically, you have to use the functions from a calculator such as this:


How obnoxious.

But precise and flexible.

Makes me a tad grumpy. [smile]

Cheers,


[monkey] Edward [monkey]

&quot;Cut a hole in the door. Hang a flap. Criminy, why didn't I think of this earlier?!&quot; -- inventor of the cat door
 
I also remember that old Richard Pryor movie and the red car. That was while I thought hat I suggested (normal float behaviour) was common knowledge and have always been extra careful around them.

It's analogous to 10 / 3 not being really equal to 3.33 or 3.3333 or even 3.33333333 in decimal arithmetic. And so 3 * 3.33333333 isn't really 10. It's the basic example we use in our company to teach freshers about REAL, FLOATs etc.

For instance, you can't use them around limit checks in DO loops. You can't for instance say:

fNum=0.
while fnum != 128.67 {
fNum=fNum+83.
fNum=fNum+45.67
}
might go in an endless loop for the same reason.

You must say while fnum < 128.67 etc.

Hope this helps (HTH).

End
 
Well yeah, 1/3 is problematic at best, but 100 + 100.67 is not. It is a very simple FP calculation. If this is an error ubiquitous to all FP processes, then 100 + 100.67 will not be properly represented in any computing language on Earth that uses an FP process.

This is not the case.

In every language I've used in the past, 100 + 100.67 summed neatly up, with no extra zeroes. If a programming language said &quot;1.5 + 1.5 = 4.34&quot;, that would be &quot;wrong&quot; and the programming language would deserve every delicious ounce of derision resultant. We allow &quot;1 / 3 = 0.333&quot; because we do understand that there are limits to FP calculation, but this isn't (or shouldn't be!) one of them.

Therefore, either I was mis-using the parseFloat, or there was some ding-dong error in JS's FP process (especially considering 100 + 100.65 and 100 + 100.68 added up neatly).

I was perfectly willing to believe the former, as I have no ego in that regard, but now I suspect the latter, which is very disappointing. To say the least.

Cheers,


[monkey] Edward [monkey]

&quot;Cut a hole in the door. Hang a flap. Criminy, why didn't I think of this earlier?!&quot; -- inventor of the cat door
 
I'm learning action script, which is an event based cousin to javascript for flash. I found this today. in &quot;action script for flash MX the definitive guide second edition&quot;

Occasinally, ActionScript calculations are rounded in undesirable ways, producing numbers such as 0.140000000000001 instead of 0.143. This happens because computers convert numbers of any base to an internal binary (much like 0.33333333 in decimal). computers have only finite precision, so they cannot perfectly represent nonterminating fractions. In order to compensate for the minute descrepancy, you should round your numbers manually if the difference will adversely affect the behavior of your code.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top