Javascript Function not working

Discussion in 'JavaScript' started by saadi123, Mar 3, 2014.

  1. #1
    I wrote a javascript code comprising Javascript function. The editor is giving me the following error and the code is not working as well.

    Error Code:
    
    function naturalSum(num1,num2) {
        var sumValue = 0;
            for (i=0;i<1000;i++)
            {
                if (i%num1 === 0 || i%num2 === 0) {
                    return sumValue += i;
                    //code
                }
           
        }
        }
    document.write(naturalSum(3,5));
    
    Code (markup):
    What does this error mean and why the code isn't working?

    Thanks.
     
    Solved! View solution.
    saadi123, Mar 3, 2014 IP
  2. sarahk

    sarahk iTamer Staff

    Messages:
    28,826
    Likes Received:
    4,541
    Best Answers:
    123
    Trophy Points:
    665
    #2
    homework?
    what is this code meant to be doing?
     
    sarahk, Mar 3, 2014 IP
  3. saadi123

    saadi123 Well-Known Member

    Messages:
    196
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    101
    #3
    Get the sum of natural numbers below 1000 which are divisible by 3 and 5.
    The code's working without the function though.
     
    saadi123, Mar 3, 2014 IP
  4. sarahk

    sarahk iTamer Staff

    Messages:
    28,826
    Likes Received:
    4,541
    Best Answers:
    123
    Trophy Points:
    665
    #4
    That's not what your code is doing at all.

    for starters, it appears that the 0%3 returns true
    I messed with this but it's not summing all the numbers because you have it returning. You need to add it to sumValue and only return after it's reached 1000.
        function naturalSum(num1,num2) {
    
            for (var i=1;i<1000;i++)
            {
                if (i%num1 === 0 || i%num2 === 0) {
                    return i;
                    //code
                }
    
            }
            return 0;
        }
        document.write(naturalSum(3,5));
    
    Code (markup):
    I still don't see a practical application for this though. If it's not homework, what are you trying to achieve?
     
    sarahk, Mar 3, 2014 IP
  5. saadi123

    saadi123 Well-Known Member

    Messages:
    196
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    101
    #5
    Nope, it's not a homework. Just trying to learn Javascript.
    BTW there's a slight change in code that I've done.
    
    function naturalSum(num1,num2) {
        sumValue = 0;
            for (i=0;i<1000;i++)
            {
                if (i%num1 === 0 || i%num2 === 0) {
                    sumValue += i;
                    //code
                }
          
        }
        }
    document.write(naturalSum(3,5));
    
    Code (markup):
    The code without function is working just fine.
    Here is the code without function

    var sumValue = 0;
            for (i=0;i<1000;i++)
            {
                if (i%3 === 0 || i%5 === 0) {
                    sumValue += i;
                    //code
                }
            }
    document.write(sumValue);
    Code (markup):
    The later code is returning the correct value but it displays "undefined" when I try to enclose it in the Javascript function.
     
    saadi123, Mar 3, 2014 IP
  6. sarahk

    sarahk iTamer Staff

    Messages:
    28,826
    Likes Received:
    4,541
    Best Answers:
    123
    Trophy Points:
    665
    #6
    at the end of the code you need to return sumValue to the outside world.

    My examples aren't right, but see how I return a value
     
    sarahk, Mar 3, 2014 IP
  7. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #7
    The logic here is all screwed up -- your use of return would only return the FIRST value encountered. You want to add them all up, THEN return the result!

    function naturalSum(num1, num2) {
    	var result = 0;
    	for (var i = 0; i < 1000; i++) {
    		if (i % num1 === 0 || i % num2 === 0) result += i;
    	}
    	return result;
    }
    
    document.write(naturalSum(3,5));
    Code (markup):
     
    deathshadow, Mar 3, 2014 IP
  8. saadi123

    saadi123 Well-Known Member

    Messages:
    196
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    101
    #8
    saadi123, Mar 4, 2014 IP
  9. #9
    BTW, you could make it way faster by eliminating redundant values. You don't need to check zero, incrementing by each number would be a fraction the operations, you just need on the second check to make sure you aren't pulling values already added in the first one.

    function naturalSum(num1, num2) {
    	var result = 0;
    	for (var i = num1; i < 1000; i += num1) result += i;
    	for (var i = num2; i < 1000; i += num2) {
    		if ((i % num1) != 0) result += i;
    	}
    	return result;
    }
    
    document.write(naturalSum(3,5));
    Code (markup):
    First loop lacking a conditional and just flat adding them would run about 3.5 times faster (assuming num1 is three), while the latter test would be a little under five times faster than your normal loop... real world together the above would execute in a little under half the time of your single loop; though the speedup would hinge on .js engine and the values you feed it.

    Might be even faster, modulo is the remainder from a divide, and divides are SLOW. A second loop inside the second addition to test against num1 and increment past it might be worth implementing if speed is an issue.
     
    deathshadow, Mar 4, 2014 IP
  10. saadi123

    saadi123 Well-Known Member

    Messages:
    196
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    101
    #10
    That's something new I've learned about Javascript today.
    Btw how can you check the speed of the execution of the Javascript code?
     
    saadi123, Mar 4, 2014 IP
  11. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #11
    It's more of a processor issue, though JavaScript's "untyped arbitrary length math" and object/string conversions re-introduce a slowness not seen on modern systems since the old 8088 days. (something I'm quite familiar with since I still write DOS games for the 5150/T1K/Jr. Apparently I didn't get the memo.). -- back in the day a most opcodes in assembly took 2 to 8 clock cycles, while a multiply or divide could take 200+ clock cycles. This is because the 8088 and 8086 didn't have "hardware math" -- they ran what's called "microcode", a small optimized on-chip program using other operations to perform those maths.

    Javascript having untyped variables and a really loose upper limit to number lengths (so called arbitrary math) is much more versatile than fixed integer math, but that comes with a staggering performance cost since basically they're running the same thing as the microcode from 30 year old processors. ALL math is floating point (especially divides), and so forth. Even addition/subtraction are (compared to compiled languages) painfully slow, with multiplication and divides even more so. Worse, now that we have all these mobile devices with ARM processors, the problems are re-introduced at the hardware level since to be frank, even with the so called floating point extensions, ARM sucks at math worse per clock cycle than a i8087 from thirty years ago.

    In many ways it's similar to something I'm using to speed up my 'retrogame' engine, BCD math, where you store all values as either one nybble (called 'packed') or one byte (called 'unpacked') per decimal digit -- which can be faster if you need to convert it to an ascii string or use it for a rendering lookup table, but is many times slower at even basic math. It's a cute thing when 0x0202 hex == 22 decimal.

    That's a topic rarely covered, because doing so reveals one of JS' biggest weaknesses, the lack of an accurate timer. While there are some new functions for latching onto the refresh rate in modern browsers, the overhead of getting to those is a pain in the ass. You can't simply do a 'settimeout' when profiling because timeouts don't start running until code STOPS running -- so if you run a tight loop of your routine over and over timer events never happen. The best one can usually do is to pull the time in ms from "new Date().getTime()" -- but that has timer accuracy issues galore.

    Some browsers only update it every 33ms, others every 30ms, some (hello IE7/earlier) only update it every 54.9ms (which is the old DOS system timer accuracy!?! Go LEGACY!). This means that using a timestamp at the start of running a fixed number of loops and a timestamp at the end can be off by as much as double the 'timer latency' -- which is why (if you follow Nyquist-Shannon rules for sampling) anything less than four times the latency (twice to account for jitter, twice again for a adequate sample pool) is inaccurate bull. If you ever see anyone touting javascript benchmarks where their results are less than 220ms apart, it's bullshit.

    So what can you do? The answer is to use the timestamp but first wait for 'rollover' at the start, then run your routine over and over until a specified amount of time MANY MANY times larger than the timer accuracy has elapsed... you then take twice the longest known timer accuracy and use that as the 'skew' or error probability.

    I actually have a small object I use for testing that shows the method in action.
    var statTimer = {
    	endTime : 0,
    	checks : 0,
    	timerStart : function(seconds) {
    		this.checks = 0;
    		/* wait for rollover to reduce inaccuracy */
    		var t = new Date().getTime();
    		do {
    			this.endTime = new Date().getTime();
    		} while (this.endTime == t);
    		this.endTime += seconds * 1000;
    	},
    	timerActive : function() {
    		this.checks++;
    		return new Date().getTime() < this.endTime;
    	}
    }
    Code (markup):
    Calculating the end time at the beginning reduces how much this routine effects the outcome result. To use it you simply do this:

    statTimer.timerStart(3);
    while (statTimer.timerActive()) naturalSum(3,5);
    document.write('Test managed ', statTimer.checks, ' Iterations.<br />');
    Code (markup):
    I do not recommend testing more than 5 seconds as if you're comparing more than three routines you'll get a 'not responding' or 'script has failed to respond' error in most browsers. Usually 3 seconds is more than sufficient to get a meaningful result.

    I made a routine that does the 'inner loop' elimination I mentioned.

    function fastSum(num1, num2) {
    	var result = 0, i, j;
    	for (i = num1; i < 1000; i += num1) result += i;
    	i = num2;
    	while (i <= 1000) {
    		j = 1;
    		while ((j < num1) && (i < 1000)) {
    			result += i;
    			i += num2;
    			j++;
    		}
    		i += num2;
    	}	
    	return result;
    }
    Code (markup):
    Which should be somewhere between 50% to 250% faster depending on the browser. I put all three together in a test here:

    http://www.cutcodedown.com/for_others/saadi123/

    The results on my i7 4700MQ 2.4ghz laptop are interesting, and really illustrate how different browser versions are.

    Opera 12 (as opposed to the steaming pile of crippleware known as Chrome with the Opera logo slapped on it)
    Raw loop by one : 439489 - Ratio 100.00%
    Twin loop by Value : 1240457 - Ratio 282.25%
    Nested while with elimination : 1484004 - Ratio 337.67%

    FireFox
    Raw loop by one : 467025 - Ratio 100.00%
    Twin loop by Value : 1919405 - Ratio 410.99%
    Nested while with elimination : 2870531 - Ratio 614.64%

    Chrome
    Raw loop by one : 513661 - Ratio 100.00%
    Twin loop by Value : 2479815 - Ratio 482.77%
    Nested while with elimination : 4935705 - Ratio 960.89%

    IE11
    Raw loop by one : 230965 - Ratio 100.00%
    Twin loop by Value : 1481444 - Ratio 641.41%
    Nested while with elimination : 4409560 - Ratio 1909.19%

    That's one HELL of a range of results, no? Notice how in IE11 the last one is comparable in speed to chrome, while the original is less than half the speed of the original in chrome? FUN STUFF! Illustrates one of the biggest issues in code optimization for JS -- every browser is different.

    Hope this helps.
     
    deathshadow, Mar 4, 2014 IP
  12. ketting00

    ketting00 Well-Known Member

    Messages:
    782
    Likes Received:
    28
    Best Answers:
    3
    Trophy Points:
    128
    #12
    Nice to here about this. It's still pretty slow. My app requests 16ms in loop execution (Data from requestAnimation function). Do know anything that boosts this thing up?
     
    ketting00, Mar 5, 2014 IP
  13. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #13
    JS isn't capable of that low a level of latency -- it just isn't. It's why high end animation with canvas is, to be frank, a joke. It's a single threaded non-interrupting non-cooperative language with piss poor timer capabilities. Even "requestAnimationFrame" doesn't really help that a whole lot from a game logic perspective; hell that redraws aren't done until you actually release execution means requestAnimationFrame won't even fire in a useful manner for use as an actual timer.

    It's why most of your WebGL and Canvas games are limited to a dreadful 30fps. Cute for making a pacman or space invaders ripoff, useless for anything more complex than that unless you don't mind the 'jittery frame rate'.
     
    deathshadow, Mar 5, 2014 IP
  14. ketting00

    ketting00 Well-Known Member

    Messages:
    782
    Likes Received:
    28
    Best Answers:
    3
    Trophy Points:
    128
    #14
    Many thanks. Great info. I work on canvas animation for years and I just know the fact. Performance is always my biggest challenge.
     
    ketting00, Mar 5, 2014 IP