What's wrong with this even/odd Javascript? - javascript

I am trying to write a very simple JS program. I want it to generate 10 random numbers between 1 and 100 and display how many of them are even and how many are odd. I've been looking all over and I can't find why this isn't working. It's displaying 0 even numbers and 10 odd numbers, no matter the combination. What am I overlooking?
function main()
{
var number = 0;
var totalNumbers = 0;
var evenNumbers = 0;
var oddNumbers = 0;
document.write("Here are ten random numbers between 1 and 100:<br><br>");
while(totalNumbers < 10)
{
number = document.write((Math.floor((Math.random()* 100)+1)) + "<br>");
if(number % 2 == 0)
{
evenNumbers++;
}
else
{
oddNumbers++;
}
totalNumbers++;
}
document.write("<br><br>Even Numbers: " + evenNumbers + "<br>" +
"Odd Numbers: " + oddNumbers);
}

document.write() does not return a number. Store the number in a variable before calling document.write().
while(totalNumbers < 10)
{
var number = Math.floor((Math.random()* 100)+1;
document.write(number + "<br>");
if(number % 2 == 0)
{
evenNumbers++;
}
else
{
oddNumbers++;
}
totalNumbers++;
}

Related

while loop test case errors

The question as per the practice course is :
Write a JavaScript program to find the maximum integer n such that (1 + 2 + ... + n <= given integer ) is true. For eg. If a given integer is 10, value of maximum integer n is 4 so that 1+2+3+4 <= 10 is true. Your output code should be in the format console.log("Value of n is ", variableName)
My code is :
var num = prompt("Enter a number");
function test(x) {
var sum = 1,
n = 1,
a = 0;
while (sum <= x) {
sum += n;
n = n + 1;
a += 1;
}
return a;
}
var output = test(num);
console.log("Result is :", output);
I'm getting the correct outputs as per the test cases I've entered(10-4,15-5,16-6,17-6) but the website says there is something wrong with the program.
What am i doing wrong?
Better answer than looping: exploit maths. Starting with Triangular number formula:
1 + 2 + ... + n = n * (n + 1) / 2
Thus, for input x, you need to find n such that
n * (n + 1) / 2 <= x
To solve this, we need to clean up the inequality, then use the quadratic equation formula:
n^2 + n <= 2x
n^2 + n - 2x <= 0
n <= (-1 + sqrt(1 + 8x)) / 2
as the final solution. e.g. for
x = 10: n <= (-1 + sqrt(81)) / 2; n <= 4
x = 16: n <= (-1 + sqrt(128)) / 2; n <= 5.156854249492381
Round the upper limit down, and you have the largest allowed integer. Translated into JavaScript:
function test(x) {
return Math.floor((Math.sqrt(8 * x + 1) - 1) / 2);
}
var num = prompt("Enter a number");
console.log("Result is :", test(num));
Consider if the passed value is 11. Then, the maximum integer n should be 4, because 1+2+3+4 < 11 is true, while 1+2+3+4+5 < 11 is false. Your current code outputs 5 for an input of 11, though, which is incorrect; your while loop is sometimes overshooting sum.
You also need to initialize sum to start at 0, not at 1.
Subtract one from a before returning it:
function test(x) {
var sum = 0,
n = 1,
a = 0;
while (sum <= x) {
sum += n;
n = n + 1;
a += 1;
console.log(a, sum);
}
return a - 1;
}
console.log(test(10));
console.log(test(11));
var num = prompt("Enter a number");
var output = test(num);
console.log("Result is :", output);
The code below should work for you. Basically, what I did was that if the input is 10, and your sum is 9, it will still go into the while loop. Then it will add n again and now your number is greater than your input (which is 10), but you still return it. Here what I did is that at the end of the while loop, if your sum is greater than your input, subtract one from a. That way it will still execute, but it will fix the problem.
Also another error I noticed was that sum started at 1, and n started at 1. You wanted 1+2+3+...+n, however using your previous method, you got 1+1+2+3+...+n.
var num = prompt("Enter a number");
function test(x) {
var sum = 0,
n = 1,
tempSum = 1,
a = 0;
while (sum <= x) {
sum += n;
n++;
a++;
if (sum > x) {
a--;
}
}
return a;
}
var output = test(num);
console.log("Result is :", output);
Your order of operation is a little funky; all you have to do is add the incrementor. The while false case will make sure the sum only passes over the number once. So when you return, reduce the number by one:
var num = prompt("Enter a number");
var output = test(num);
console.log("Result is :", output);
function test(num){
let sum = 0
let inc = 0
while(sum<=num)
sum+=++inc
return --inc;
}
This is a reduced version of your code, basically we increment first the number to add (n) in each iteration, and then we add it to the variable holding the sum. When the loop conditions evaluates to false you need to decrement one to n to get your value:
var num = prompt("Enter a number");
function test(x)
{
var sum = 0, n = 0;
while (sum <= x)
{
sum += (++n);
}
return --n;
}
var output = test(num);
console.log("Result is :", output);
I think this will work for you:
var num = prompt("Enter a number");
function test(x) {
var sum = 1,
n = 0;
while ((sum+n) <= x) {
n = n + 1;
sum += n;
}
return n;
}
var output = test(num);
console.log("Result is :", output);
Try below function to find max Number
function maxNumber(a){
var i=1,sum=0,maxNumber=0;
while(sum<=a) {
sum=sum+i;
if(sum<=a)
{
maxNumber=i;
}
i+=1;
}
return maxNumber;
}
doubled checked condition sum<=a to preserve the previous loop value and if condition not satisfied that means current loop value is not useful so returned preserved value of previous loop
Output tested :
Below will help you get the job done.
var num = prompt("Enter a number");
function findMaxNumber(num){
var sum = 0;
var counter = 0;
while(sum < num){
if(sum + counter > num){
break; // Exit loop
}
sum = sum + counter;
counter++;
}
return --counter; // Loop will cause this to be 1 higher than the max int.
}
console.log('Result is: ' + findMaxNumber(num));

Getting an incorrect answer with a mercende prime number generator

all! recently i've been trying to build a mercende prime number producer/generator, using the lucas lehmer method of testing. the code works for the first 4 numbers, and then fails for the rest. any suggestions? thanks!
var totalPrimes = Math.floor(prompt("What would you like the upper limit of
our search for primes to be?"));
for (var i = 2; i < totalPrimes; i++) {
var lucasNum = 4;
var curNumber = (Math.pow(2, (i+1))-1);
for (var x = 0; i-1 > x; x++) {
if (lucasNum / curNumber > 1) {
lucasNum = (Math.pow(lucasNum, 2)-2);
} else {
lucasNum = (Math.pow(lucasNum, 2)-2);
}
}
if (lucasNum % curNumber === 0) {
console.log("The number " + curNumber + " is prime");
} else {
console.log("The number " + curNumber + " is not prime");
}
}
The mantissa (or significand) of a Javascript number is 53-bit wide. Therefore, the biggest integer that can be stored in full precision is:
2^53 - 1 = 9007199254740991 = Number.MAX_SAFE_INTEGER
(You may want to read this page for more details.)
Your algorithm is likely to hit this limit very quickly. The precision explosion occurs within this statement:
lucasNum = (Math.pow(lucasNum, 2)-2);
which is included in a loop.

How can I count the number of zero decimals in JavaScript?

How do I get the number of zero decimals behind the comma (but not the total)? So to illustrate an example:
0.00001 > 4
0.000015 > 4
0.0000105 > 4
0.001 > 2
I am looking for methods that are efficient (meaning that they optimize the calculation time).
You can use logarithms to find the magnitude of the number:
var x = 0.00195;
var m = -Math.floor( Math.log(x) / Math.log(10) + 1);
document.write(m); // outputs 2
Later versions of JavaScript have Math.log10, so it would be:
var x = 0.00195;
var m = -Math.floor( Math.log10(x) + 1);
document.write(m); // outputs 2
How using the base-10 logarithm of the numbers works:
x
Math.log10(x)
Math.floor(Math.log10(x) + 1 )
0.1
-1
0
0.01
-2
-1
0.015
-1.8239…
-1
0.001
-3
-2
0.00001
-5
-4
0.000015
-4.8239…
-4
0.0000105
-4.9788…
-4
Use a regex to match the number of zeros after a decimal point and then count them.
var zeros = float.toString().match(/(\.0*)/)[0].length - 1;
DEMO
Use this one:
function numberOfZeros(n) {
var c = 0;
while (!~~n) {
c++;
n *= 10;
}
return c - 1;
}
document.write(numberOfZeros(0.00065));
This code does the following: it multiplies the number by ten as long as it can be truncated to something not equal 0. The truncation operator "~~" is very performant, because it works with byte representation of the number directly.
It doesn't use any string operations and does exactly what you want: counts the zeros.
//my answer
function t1()
{
var num = 0.0000005323;
numOfZeroes = 0;
while(num < 1)
{
numOfZeroes++;
num *= 10;
}
}
//others
//Andrew Morton's answer
//https://stackoverflow.com/a/31002148/1115360
function t2()
{
var num = 0.0000005323;
var m = -Math.floor( Math.log10(num) + 1);
}
//Amy's Answer
//https://stackoverflow.com/a/31002087/4801298
function t3()
{
var r = 0.0000005323;
var count=0;
var splited = r.toString().split(".")[1];
for(var i=0;i<splited.length;i++)
{
if(splited[i]==0)
{
count++;
}
else
{
break;
}
}
}
//Ted's Answer
//https://stackoverflow.com/a/31002052/4801298
function t4()
{
var number = 0.0000005323;
var numberAsString = number.toString();
var decimalsAsString = numberAsString.substr(numberAsString.lastIndexOf('.')+1);
var leadingZeros = decimalsAsString.substr(0, decimalsAsString.lastIndexOf('0')+1).length;
}
//Bartłomiej Zalewski's answer
//https://stackoverflow.com/a/31001998/4801298
function t5()
{
var n = 0.0000005323;
var c = 0;
while (!~~n) {
c++;
n *= 10;
}
return c - 1;
}
//Andy 's answer
//https://stackoverflow.com/a/31002135/4801298
function t6()
{
var float = 0.0000005323;
var zeros = float.toString().match(/(\.0*)/)[0].length - 1;
}
//Praveen's answer
//https://stackoverflow.com/a/31002011/4801298
function t7()
{
var a = 0.0000005323;
return (a.toString().replace("0.", "").split("0").length - 1);
}
//benchmark function
function bench(func)
{
var times = new Array();
for(var t = 0; t < 100; t++)
{
var start = performance.now();
for(var i = 0; i < 10000; i++)
{
func();
}
var end = performance.now();
var time = end - start;
times.push(time);
}
var total = 0.0;
for(var i=0, l=times.length; i<l; i++)
total += times[i];
var avg = total / times.length;
return avg;
}
document.write('t1: ' + bench(t1) + "ms<BR>");
document.write('t2: ' + bench(t2) + "ms<BR>");
document.write('t3: ' + bench(t3) + "ms<BR>");
document.write('t4: ' + bench(t4) + "ms<BR>");
document.write('t5: ' + bench(t5) + "ms<BR>");
document.write('t6: ' + bench(t6) + "ms<BR>");
document.write('t7: ' + bench(t7) + "ms<BR>");
Note:
This would only work with numbers less than 1 of course. Otherwise, just remove numbers left of the decimal point first, like
num -= num % 1;
need to compare this to another way.
a while later...
I would like a better way to bench these function though. I might have my calculation wrong. I'm adding other peoples answers into the test. I'm now attempting to use the performance API
a bit later than before
AHA! Got it working. Here are some comparisons for you.
You can use something like this:
function num (a) {
return (a.toString().replace("0.", "").split("0").length - 1)
}
Here is a working example (a bit lengthy for clarity):
var number = 0.0004342;
var numberAsString = number.toString();
var decimalsAsString = numberAsString.substr(numberAsString.lastIndexOf('.')+1);
var leadingZeros = decimalsAsString.substr(0, decimalsAsString.lastIndexOf('0')+1).length;
// leadingZeros == 3
Convert the number in to a string and split it with the dot (.). Using the for loop to count the zeros occurrences.
var r = 0.0000107;
var count=0;
var splited = r.toString().split(".")[1];
for(var i=0;i<splited.length;i++)
{
if(splited[i]==0)
{
count++;
}
else
{
break;
}
}
console.log(count);
Node.js 9.0.0
I was looking for a solution without converting or the O(n) approach. Here is what solution I made by O(1).
Part of finding decimal by log – caught from #AndrewMorton, but it might be laggy with the divider: log(10) – 2.302585092994046.
Example
const normalize = (value, zeroCount) => {
const total = 10 ** zeroCount
const zeros = Math.floor(-Math.log10(value / total))
return value * (10 ** zeros)
}
Usage
normalize(1510869600, 13) // 1510869600000
normalize(1510869600, 10) // 1510869600

Double Maths Random in Array with Javascript

I need your help because I'm totally lost with a javascript exercise (I learn alone).
I cut the exercice in steps
I generate an aleatory number between 3 and 20 (with Maths Random)
I generate an array of 100 cells: In each cells, there is one " _ "
If the number is 5: 5 " _ " is aleatory replaced by a " # " (second Maths Random)
I think my cut is good but I can't write it in code.
Before this exercise I've done exercises easier with maths random but now it's more diffult for me.
Some can help me to create the code?
Thank you very much
edit: I tried to do something but without maths random.
function hashtagLine(){
var number = prompt( "Saisissez un nombre entre 3 et 10" );
var line = "";
if (number >= 1 && number <= 10){
for ( var i = 1; i <= 100; i++ ) {
if ( i % number === 0 ) {
line += "#";
} else {
line += "_";
}
}
console.log( line );
} else {
alert( "vous avez entré un nombre qui ne correspond pas" );
}
}
hashtagLine();
Here is a simple implementation:
HTML
<table id="table"></table>
JS
var t = document.getElementById('table');
var rnd = Math.ceil(Math.random() * 17 + 3);
var string = '<tr>';
for (var i = 1; i <= 100; i++) {
if (i == rnd) {
string += '<td>#</td>';
} else {
string += '<td>_</td>';
}
// for new row...
if (i % 10 == 0) {
string += '</tr><tr>';
}
}
string += '</tr>';
t.innerHTML = string;
But if you're trying to learn the language, it's best to try yourself, not just have somebody hand you the answer.
It is still not clear to me what you are trying to achieve, but here is some code that may help you. If you come back with more information then I may be able to help you some more.
Math.random
// get reference to out output element
var pre = document.getElementById('out');
// Returns a random integer between min (included) and max (excluded)
// Using Math.round() will give you a non-uniform distribution!
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
function hashtagLine() {
var min = 3,
max = 20,
cells = 100,
number = getRandomInt(min, max + 1),
line = [],
index;
// create the line array of length cells
for (index = 0; index < cells; index += 1) {
// unclear what you are trying to do here!
if (index % number === 0) {
line.push('#');
} else {
line.push('_');
}
}
// output the array as a line of text
pre.textContent += line.join('') + '\n';
}
// Add a click event listener to our generate button
document.getElementById('generate').addEventListener('click', hashtagLine, false);
<button id="generate">Generate</button>
<pre id="out"></pre>

Always display number with 3 digits and descriptor

Using Javascript, I want to format a number to always display 3 digits, along with it's proper identifier (ex: Million, Thousand). If under 100,000, the number should only show the "thousands" digits
All numbers will be integers above zero, and the highest numbers will be in the trillions.
A few examples of what I'm looking for:
1 Thousand
13 Thousand
627 Thousand
2.85 Million
67.9 Million
153 Million
9.52 Billion
etc...
All of the solutions I tried ended up becoming spaghetti code, and I am hoping someone can find a clean, smart solution.
EDIT:
I ended up using part of RobG's solution, but worked out the specifics on my own. I added rounding as well
function getNumberName(num) {
var numNames = ['', 'Thousand', 'Million', 'Billion', 'Trillion'];
num = num.toString();
var len = num.length - 1;
return numNames[len / 3 | 0];
}
function test(num) {
var numStr = num.toString();
if (num < 1000) {
return numStr;
} else if (num < 1000000) {
return numStr.slice(0, -3) + "," + numStr.slice(-3);
}
numStr = Math.round(parseFloat(numStr.slice(0, 3) + "." + numStr[3])).toString() + Array(numStr.slice(3).length + 1).join("0");
var remainder = numStr.length % 3;
var before = numStr.slice(0, remainder);
var after = numStr.slice(remainder, 3);
var sep = "";
if (before.length) {
sep = ".";
}
return before + sep + after + " " + getNumberName(num);
}
var nums = [0, 1, 12, 123, 1234, 12345, 123456, 1237567, 12325678, 123856789, 123e7, 125e8, 123.6e9, 123e10];
nums.forEach(function(num) {
document.write(num + ": $" + test(num) + "<br/>");
});
For integers, you can try shortening the number to the required number of places, then adding a name, e.g.
// For integers
function getNumberName(num) {
var numNames = ['','Thousand','Million','Billion'];
var num = num.toString()
var len = num.length - 1;
var pow = numNames[len/3 | 0];
return pow;
}
// For integers
function abbreviateNumber(num, places) {
places = places || 0;
var len = num.toString().length - 1;
var pow = len/3 | 0
return (num < 1000? num : num/Math.pow(10, pow*3)).toFixed(places);
}
function getNumberAbbr(num, places) {
return abbreviateNumber(num, places) + ' ' + getNumberName(num);
}
var nums = [0,1,12,123,1234,12345,123456,1234567,12345678,123456789,123e7]
nums.forEach(function(num) {
console.log(num + ' : ' + getNumberAbbr(num,1));
});
The above is not complete. There should be a limit applied so that beyond, say 1 trillion, it stops shortening the number.
There might be a better way but this will work:
function getTextNums(number) {
if ((number/1000000) < 1) {
var n = number.toString();
var first3 = n.substring(0, 3);
console.log(first3 + "Thousand");
} else if((number/1000000000) < 1) {
var n = number.toString();
var first3 = n.substring(0, 3);
console.log(first3 + "Million");
} else if((number/1000000000000) < 1) {
var n = number.toString();
var first3 = n.substring(0, 3);
console.log(first3 + "Billion");
} else if((number/1000000000000000) < 1) {
var n = number.toString();
var first3 = n.substring(0, 3);
console.log(first3 + "Trillion");
} else {
}
}
getTextNums(4533544433000)

Categories