-1

Context

I have a snippet of code which allows a user to click on a 'variable (arbitrary) element', be prompted for a number, and see a processed version of that number produced in/on the element they clicked, based on a 'variable function'. I'll provide a more thorough description and the original code below. Skip to the bottom for the questions.

Thorough description

I have a function that looks like square(root) { return root * root; }. Obviously it takes a number and returns that number times itself. I've got another one like this printNum(input) { return input; } -Hopefully no explanation is needed.

The browser calls them with an event listener aimed at var element = document.getElementById("unique-key") which looks like element.addEventListener('click', promptFunction);.

And promptFunction uses var functionPlug =[functionsListedAbove]; to point input from window.prompt('inputvar') to element.innerHTML

Original Code

//where to write
var element = document.getElementById("module");

//what to write
var functionPlug = printNum;



//how to write
function square(root)      { return root * root; }
function printNum(input)   { return input * input / input; }



//write
function promptFunction()  { element.innerHTML = functionPlug(window.prompt('inputvar')); }



//When to write
element.addEventListener('click', promptFunction);
//promptFunction(); --immediately
body {

 background-color: #3A3C3D;   /*alt color #CCA #3A3C3D*/
 margin: 0;
 overflow: hidden;     /*top stop the extended shadow element height from causing the page to scroll*/
}



.backDrop {

 background-color: #FFF;    /*alt colors #ACA null #CCA*/
 margin: auto;
 height: 100vh; width: 720px;
}
.backDrop:before {

 box-shadow: 0 0 20px black;
 content:'';
 position: absolute;
 height: 200vh; width: 720px;
 margin: auto;
 z-index: -1;
}



.lineBreak {

 height: 16px;
}



.module {

 border-left: 2px dotted red;
 border-radius: 5px;
 box-shadow: 0 0 5px -2px rgba(0,0,0,.4);
 margin: auto;
 height: 270px; width: 480px;
}
<body><!--All the comments you'll see below are meant to null 'white space' between layout elements--><!--
 --><div class="backDrop" id="backDrop"><!--
  --><div class="lineBreak"></div><!--
  --><div class="module" id="module"></div>
 </div>

Now for my question

It seems that my square function works perfectly, but printNum has some very strange behavior I need explained to me.

input ranging from 9 to 9999999 produces the number you'd expect.

input 99999999 produces 99999998.99999999

input 999999999 to 9999999999 produces the numbers you would expect.

input 999999999999 produces 99999999999.00002

input 9999999999999 to 999999999999999 produces the number you'd expect

and finally 9999999999999999 produces 10000000000000000

That last one I think I understand because it's sixteen digits, but I'd still like to get out of the realm of speculation.

Are there other numbers the produce strange results? What are they and why do they do it? Also how can I avoid e notation?

Musixauce3000
  • 549
  • 1
  • 3
  • 11
  • Your numbers don't sound right, any integer in between 2^53 -1 and its negative counterpart should be considered safe integers, that is they don't use floating point. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER. What does [isSafeInteger](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger) return? – Ruan Mendes Dec 26 '15 at 01:18
  • You should show a simple example of what you are calling exactly, you have way too much code that is irrelevant to the question – Ruan Mendes Dec 26 '15 at 01:23

1 Answers1

1

Your text says printNum(input) { return input; }, but in the original code, there is function printNum(input) { return input * input / input; }. That is important.

The Question

So basically, you question can be summed up to why does javascript do this:

99999999 * 99999999 / 99999999 == 99999998.99999999
999999999999 * 999999999999 / 999999999999 == 99999999999.00002
9999999999999999 == 10000000000000000

BTW, the second one (with 999999999999) is not correct in my Chrome

The Answer

Many programming langauages make a clear distinction between an integer and a floating point number (because CPU does too). JavaScript does not. It has a Number type which is in fact a double-precision floating point (double in C), but looks like an integer whenever possible.

A floating point number can show much bigger numbers than integers and can have decimals, but it comes at the cost of losing precision, especially with big numbers.

You will want to know how big. You can check Number.MAX_SAFE_INTEGER. For number bigger than that, there is no guarantee that they will have the precision of an integer.

For example:

Number.MAX_SAFE_INTEGER == 9007199254740991
Number.MAX_SAFE_INTEGER + 1 == 9007199254740992
Number.MAX_SAFE_INTEGER + 2 == 9007199254740992
Number.MAX_SAFE_INTEGER + 1 == Number.MAX_SAFE_INTEGER + 2

In your case, you have problems because:

99999999 * 99999999 > Number.MAX_SAFE_INTEGER
9999999999999999 > Number.MAX_SAFE_INTEGER

More

If you still don't understand why there is a problem with floating point numbers, see these:

http://www.w3schools.com/js/js_numbers.asp

Floating point inaccuracy examples

Community
  • 1
  • 1
zvone
  • 18,045
  • 3
  • 49
  • 77
  • I'm realizing by reading your answer that there is probably no for me to ask the actual question I need to ask, and if there was, it's unlikely it could be answered in a post on stackoverflow. But you have managed to introduce me to many new concepts I doubt I'd have ever gotten around to reading about on my own, and you've exposed some critical under the hood knowledge about the language and in so doing, solved my problem. Thank you. – Musixauce3000 Dec 26 '15 at 01:58
  • @Musixauce3000 I'm glad it helps :) BTW, I think must of the time people have programming questions, their main trouble is to figure out what to ask. After that, the answers are easy. – zvone Dec 26 '15 at 02:05