If/else condition is killing my function - javascript

I am new to javascript and I was trying to make a simple calculator for 2 values from input fields, plus an operator from a select drop down.
Plus, a button that runs a function that writes the result of the operation.
I have been building this, however, I am stuck in the stage of the con dition:
I want to:
- if slect +, do a sum
- if select - do subtraction
- if select * do multiplication
- if select / do a division
Here is my function
function multiply()
{
var x = document.getElementById('x_value').value;
var y = document.getElementById('y_value').value;
var signal = get_operator();
var u = parseInt(x,10) + parseInt(y,10);
var v = x - y;
var w = x * y;
var z = x / y;
/*
if(signal == plus)
{
document.getElementById('result').innerHTML = u;
}
else if(signal == minus)
{
document.getElementById('result').innerHTML = v;
}
else if(signal == times)
{
document.getElementById('result').innerHTML = w;
}
else
{
document.getElementById('result').innerHTML = z;
}
*/
}
Note that I have commented the logical test on purpose.
The get_operator function is working well
function get_operator(operator)
{
var operator = document.getElementById("operation").value;
return operator;
}
and the print result button itself is working.
If I put for example
function multiply()
{
var x = document.getElementById('x_value').value;
var y = document.getElementById('y_value').value;
var signal = get_operator();
var u = parseInt(x,10) + parseInt(y,10);
var v = x - y;
var w = x * y;
var z = x / y;
document.getElementById('result').innerHTML = u /*[or any other of my values]*/;
}
so, the issue is clearly with the if/else condition test. Because, when I use it, the button stops working.
Could you please be so kind as to give me some hint?
Thank you in advance

You need to parse the strings into numbers for all operations, not only additions:
x = parseInt(x, 10);
y = parseInt(y, 10);
You need to compare your operator to a string value:
if (signal == 'plus') { ... }
else if (signal == 'minus') { ... }
else ...
The fixed code then looks like:
function get_operator(operator) {
var operator = document.getElementById("operation").value;
return operator;
}
function multiply() {
var x = document.getElementById('x_value').value;
var y = document.getElementById('y_value').value;
var signal = get_operator();
x = parseInt(x, 10);
y = parseInt(y, 10);
var u = x + y;
var v = x - y;
var w = x * y;
var z = x / y;
var z = x / y;
if (signal == 'plus') {
document.getElementById('result').innerHTML = u;
} else if (signal == 'minus') {
document.getElementById('result').innerHTML = v;
} else if (signal == 'times') {
document.getElementById('result').innerHTML = w;
} else {
document.getElementById('result').innerHTML = z;
}
}
document.getElementById("compute").addEventListener("click", function(event) {
multiply();
});
<input type="text" id="x_value">
<input type="text" id="y_value">
<select id="operation">
<option value="plus">+</option>
<option value="minus">-</option>
<option value="times">*</option>
<option value="divide">/</option>
</select>
<button id="compute">Compute</button>
<div id="result"></div>
A much cleaner way to implement the same functionality is given by:
const operations = {
"plus": (a, b) => a + b,
"minus": (a, b) => a - b,
"times": (a, b) => a * b,
"divide": (a, b) => a / b,
}
const compute = document.getElementById("compute");
const operator = document.getElementById("operator");
const first = document.getElementById("first-operand");
const second = document.getElementById("second-operand");
const result = document.getElementById("result");
compute.addEventListener("click", () => {
const operation = operations[operator.value];
result.textContent = operation(first.valueAsNumber, second.valueAsNumber);
});
<input type="number" id="first-operand">
<input type="number" id="second-operand">
<select id="operator">
<option value="plus">+</option>
<option value="minus">-</option>
<option value="times">*</option>
<option value="divide">/</option>
</select>
<button id="compute">Compute</button>
<div id="result"></div>

Related

How to retain the value when returned

is there a way where x and y, when returned, can retain the value that has been inputted instead of being undefined?
Just in case you need the objective of the code here it is:
Call the function inputNumber to accept 2 values (var x and y turned into int a and b) then call getAverage. Call inputNumber again to input the value for var z turned into int c then call checkInterval.
Here is my code:
var i = 0;
function inputNumber() {
if(i == 1){
var z = prompt("Input the value of c");
var c = parseInt(z);
checkInterval(a,b,c);
}else{
var x = prompt("Input the value of a");
var y = prompt("Input the value of b");
return x;
return y;
}
}
var a = parseInt(x);
var b = parseInt(y);
getAverage(a,b);
function getAverage(a,b) {
average = (a + b)/2;
div1.innerHTML = "The average of a and b is " + average;
i++;
return i;
}
inputNumber();
function checkInterval(a,b,c) {
if(a<b && a<c<<b || b<a && b<c<a){
div2.innerHTML = "c is an interval of a and b";
alert("TRUE");
}else{
div2.innerHTML = "c is not an interval of a and b";
alert("FALSE");
}
}
<body onload="inputNumber()">
<div id="div1"></div>
<div id="div2"></div>
</body>
I have updated your solution with my interpretation.
Some issues that I identified in your code.
A javascript function cannot return more that one value. In that scenario, you have to go for returning a javascript object.
Also there was some issue in your comparison logic in checkInterval function, I have implemented my own logic there.
var i = 0;
const div1 = document.getElementById('div1');
const div2 = document.getElementById('div2');
const { x, y } = inputNumber();
function inputNumber() {
if (i == 1) {
var z = prompt("Input the value of c");
var c = parseInt(z);
checkInterval(a, b, c);
} else {
var x = prompt("Input the value of a");
var y = prompt("Input the value of b");
i++;
return {
x: x,
y: y,
}
}
}
var a = parseInt(x);
var b = parseInt(y);
getAverage(a, b);
function getAverage(a, b) {
average = (a + b) / 2;
div1.innerHTML = "The average of a and b is " + average;
return i;
}
inputNumber();
function checkInterval(a, b, c) {
if ((a < c && c < b) || (b < c && c < a)) {
div2.innerHTML = "c is an interval of a and b";
alert("TRUE");
} else {
div2.innerHTML = "c is not an interval of a and b";
alert("FALSE");
}
}
<div id="div1"></div>
<div id="div2"></div>
Your variables x and y are function scoped so they are available only within the function where they are defined. So, you need to define it in the outer scope so that all functions have access to it. See the code snippet below, it should help!
Also, avoid using innerHTML use innerText or textContent instead.
var x;
function demo() {
x = prompt("Enter a number");
after();
}
function after() {
alert("Your number is " + x);
}
<body onload="demo()">
</body>

What to do with the message " 'variable' is declared but its value is never read."

I'm working on a function that takes 2 integers and returns the sum of every number between(and including) them.
I also want it to work when the first integer x is larger than the second y, for that I've written this:
if (x > y) {
let temp = x;
x = y;
y = x;
}
However, I get this message on Visual Studio Code:
'temp' is declared but its value is never read.
What is the problem?
Also, this is the complete script:
const sumAll = function( x , y ) {
if (x !== Math.abs(x) || y !== Math.abs(y)) return ("ERROR");
if (typeof x !== "number" || typeof y !== "number") return ("ERROR");
if (x > y) {
let temp = x;
x = y;
y = x;
}
let finalSum = 0;
for (i = x; i <= y; i++){
finalSum += i;
}
return finalSum;
}
As you are just setting the value and not using the variable, that's why it is showing that message.
You might wanted to have the below code
if (x > y) {
let temp = x;
x = y;
y = temp;
}
You don't need a temporary variable to swap variables values, just use Destructuring assignment:
let x = 10;
let y = 7;
if (x > y) {
[x, y] = [y, x];
}
console.log('x =', x);
console.log('y =', y);

Having trouble generating a voxel sphere

I'm trying to generate the coordinates for a sphere with a given radius, but am only managing to produce a cylinder and I'm not really figuring out why. Here's my current code:
function makeSphere(radius){
var sphere3D = {};
var radiusX = radius + 0.5;
var radiusY = radius + 0.5;
var radiusZ = radius + 0.5;
var invRadiusX = 1 / radiusX;
var invRadiusY = 1 / radiusY;
var invRadiusZ = 1 / radiusZ;
var ceilRadiusX = Math.ceil(radiusX);
var ceilRadiusY = Math.ceil(radiusY);
var ceilRadiusZ = Math.ceil(radiusZ);
var nextXn = 0;
forX: for (var x = 0; x <= ceilRadiusX; ++x) {
var xn = nextXn;
nextXn = (x + 1) * invRadiusX;
var nextYn = 0;
forY: for (var y = 0; y <= ceilRadiusY; ++y) {
var yn = nextYn;
nextYn = (y + 1) * invRadiusY;
var nextZn = 0;
forZ: for (var z = 0; z <= ceilRadiusZ; ++z) {
var zn = nextZn;
nextZn = (z + 1) * invRadiusZ;
var distanceSq = lengthSq(xn, yn, zn);
if (distanceSq > 1) {
if (z == 0) {
if (y == 0) {
break forX;
}
break forY;
}
break forZ;
}
if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1) {
continue;
}
sphere3D[[x,y,z]] = true;
sphere3D[[-x,y,z]] = true;
sphere3D[[x,-y,z]] = true;
sphere3D[[x,y,-z]] = true;
sphere3D[[-x,-y,z]] = true;
sphere3D[[x,-y,-z]] = true;
sphere3D[[-x,y,-z]] = true;
sphere3D[[-x,-y,-z]] = true;
}
}
}
}
function lengthSq(x, y, z) {
return (x * x) + (y * y) + (z * z);
}
function lengthSq(x, z) {
return (x * x) + (z * z);
}
Which gives the following output.
Any ideas on where I'm messing up? Thanks in advance for your attention.
Here's an approach that might be easier to follow. You'll want to break your code up into four parts:
Generating a set of points p within a particular n-dimensional domain
Filtering the set of points to those q that are within 1 unit of a spherical surface defined by a radius and n-dimensional origin
Reflecting the set of points across each of the Cartesian axes intersecting at the origin to create the reflected set of points r
Adding the set of points r to an object nSphere
Below is a set of functions that address each of these concerns to create an n-sphere.
// 0-sphere of radius 5 centered at [6]
console.log(makeNSphere(5, 6)); // { r: [6 - 5], [6 + 5] }
// 2-sphere of radius 2 centered at [0, 0, 0]
console.log(makeNSphere(2, 0, 0, 0));
function makeNSphere (radius, ...origin) {
function onSurface (p) {
const d = distance(
p.map(
(x, i) => x - origin[i]
)
);
return Math.abs(d - radius) < 1;
}
const nSphere = {};
const ps = range(
...origin.map(
x => [x, x + radius + 1]
)
);
const reflection = reflect(...origin);
for (const q of where(ps, onSurface)) {
for (const r of reflection(...q)) {
nSphere[r] = true;
}
}
return nSphere;
}
function distance (p) {
let sum = 0;
for (const x of p) {
sum += x * x;
}
return Math.sqrt(sum);
}
function* range (constraints = [], ...rest) {
const base = rest.length === 0;
let begin = 0;
let end = Infinity;
let increment = 1;
switch (constraints.length) {
case 0: break;
case 1: [end] = constraints; break;
case 2: [begin, end] = constraints; break;
default: [begin, end, increment] = constraints; break;
}
for (let i = begin; i < end; i += increment) {
if (base) {
yield [i];
continue;
}
for (const a of range(...rest)) {
yield [i, ...a];
}
}
}
function* where (ps, predicateFn) {
for (const p of ps) {
if (predicateFn(p)) {
yield p;
}
}
}
function reflect (...axes) {
return function* recurse (x, ...rest) {
if (rest.length === 0) {
yield* base(x);
return;
}
for (const xs of recurse(...rest)) {
yield* base(x, ...xs);
}
}
function* base (x, ...rest) {
yield [x, ...rest];
const axis = axes[axes.length - rest.length - 1];
const y = axis - (x - axis);
if (x !== y) {
yield [y, ...rest];
}
}
}
Not sure if this solves you problem but you can't have 2 functions having the same name. In your case, the second lengthSq() will supersede the first one even if the parameters are different.
There is no native function overloading in Javascript. However you can try these suggestions if it important to stick with same function name that handle multiple parameters Function overloading in Javascript - Best practices
The alternative is to rename it as as lengthSqXZ(x, z) if you are using it elsewhere outside the code you have provided.

How to add two big numbers in javascript?

I have two text boxes. Each will take input up to thousand digits.
Now i want to add these two numbers. My question is what data type should i use to store the result?
I have tried this:
<script>
var x = 'Thousand digit of number'
var y = 'Thousand digit of number'
var z = x + y
</script>
but i am getting result in exponential form. How to store the result and display it?
Yet another solution, because it's faster and cleaner.
function add(A, B) {
const AL = A.length
const BL = B.length
const ML = Math.max(AL, BL)
let carry = 0, sum = ''
for (let i = 1; i <= ML; i++) {
let a = +A.charAt(AL - i)
let b = +B.charAt(BL - i)
let t = carry + a + b
carry = t/10 |0
t %= 10
sum = (i === ML && carry)
? carry*10 + t + sum
: t + sum
}
return sum
}
> add(
'9999999999999999999999999999999999999999999999999999999999999999999999999999',
'999999999999999999999999999999999999999'
)
> "10000000000000000000000000000000000000999999999999999999999999999999999999998"
Use BigInt as described here: https://stackoverflow.com/a/56370672/641913
const z = BigInt(x) + BigInt(y);
console.log(z.toString());
Here is another solution not so different from others you can find in the internet (consider that it doesn't work with negative numbers!):
function sums(arg1, arg2) {
var sum = "";
var r = 0;
var a1, a2, i;
// Pick the shortest string as first parameter and the longest as second parameter in my algorithm
if (arg1.length < arg2.length) {
a1 = arg1;
a2 = arg2;
}
else {
a1 = arg2;
a2 = arg1;
}
a1 = a1.split("").reverse();
a2 = a2.split("").reverse();
// Sum a1 and a2 digits
for (i = 0; i < a2.length; i++) {
var t = ((i < a1.length) ? parseInt(a1[i]) : 0) + parseInt(a2[i]) + r;
sum += t % 10;
r = t < 10 ? 0 : Math.floor(t / 10);
}
// Append the last remain
if (r > 0)
sum += r;
sum = sum.split("").reverse();
// Trim the leading "0"
while (sum[0] == "0")
sum.shift();
return sum.length > 0 ? sum.join("") : "0";
}
// Test
function testEquals(expected, actual) {
if (expected == actual)
console.log("OK: " + expected);
else
console.error("ERROR: " + expected + " != " + actual);
}
testEquals("100", sums("99", "1"));
testEquals("100", sums("00099", "0001"));
testEquals("10000000000", sums("9999999999", "1"));
testEquals("10000010101", sums("9999999999", "10102"));
testEquals("0", sums("0", "0"));
testEquals("1", sums("0", "1"));
testEquals("9", sums("8", "1"));
testEquals("9", sums("1", "8"));
testEquals("10000000000000000000000000000000000000000", sums("9999999999999999999999999999999999999999", "1"));
Input the numbers as string and add each characters each other as array something like this:
function add() {
document.getElementById("demo").innerHTML = "";
var x = document.getElementById("txt1").value;
var y = document.getElementById("txt2").value;
var len;
var lenx = x.length;
var leny = y.length;
var x1,y1,rem,div=0;
if(lenx>leny) len = lenx; else len = leny;
for(var i=0;i<len;i++){
if(i>=lenx) x1 = 0;
else x1 = parseInt(x[lenx-i-1]);
if(i>=leny) y1 = 0;
else y1 = parseInt(y[leny-i-1]);
rem = (x1+y1+div)%10;
div = Math.floor((x1 + y1+div)/10);
document.getElementById("demo").innerHTML = rem + document.getElementById("demo").innerHTML;
}
if(div>0){
document.getElementById("demo").innerHTML = div + document.getElementById("demo").innerHTML;
}
}
Here the code: https://jsfiddle.net/mtsL1k2x/5/
Note: this is only for natural numbers. You can modify depending on your inputs
Either use a big number library like https://mathjs.org/docs/datatypes/bignumbers.html , or you can use something lighter weight (but easy to understand) like http://www.discoversdk.com/knowledge-base/arbitrary-length-integer-addition-in-javascript
Well, if you want to do this without using BigInt or any third-party Library, then I don't think you need to convert to an array, you can use the charAt() function to add the individual characters at each point in the string. You would have to use the for loop starting from its maximum value and reducing till its lowest. The code snippet is below;
function add(a, b) {
let sum='';
let z,x;
let r=0;
if (a.length>=b.length){
z=a;
x=b;
}
else{
z=b;
x=a;
};
let p=x.length;
for (let i=z.length;i>0;i--){
let t=((p>0)?parseInt(x.charAt(p-1)):0)+parseInt(z.charAt(i-1))+r;
sum=(t%10)+sum;
r=t<10?0:Math.floor(t/10);
p=p-1;
};
if (r>0){sum=r+sum};
return sum;
};
function add(a, b) {
a = a.split("").reverse();
b = b.split("").reverse();
let maxLen=Math.max(a.length, b.length);
let sum = [];
let remainder = 0;
for (let i = 0; i < maxLen; i++) {
let x = parseInt(a[i]) ? parseInt(a[i]) : 0;
let y = parseInt(b[i]) ? parseInt(b[i]) : 0;
let digit = (x + y + remainder) % 10;
remainder = Math.floor((x + y + remainder) / 10);
sum.unshift(digit);
}
if (remainder) {sum.unshift(remainder)}
return sum.join("");
}
function add(x, y) {
//this function adds two extremely large numbers, negative and/or positive
var temp, borrow=false, bothNeg=false, oneNeg=false, neg=false;
if (x < 0 && y < 0) { bothNeg = true; x = -x; y = -y; }
else if (x < 0 || y < 0) {
oneNeg = true;
if (Math.abs(x) == Math.abs(y)) { x = 0; y = 0; }
else if (x < 0 && Math.abs(x) > Math.abs(y)) { neg = true; x = -x; y = -y; }
else if (x < 0 && Math.abs(x) < Math.abs(y)) { temp = y; y = x; x = temp; }
else if (y < 0 && Math.abs(x) < Math.abs(y)) { neg = true; temp = y; y = -x; x = -temp; }
}
x = parseInt(x*1000000000/10).toString();
y = parseInt(y*1000000000/10).toString();
var lenx=x.length, leny=y.length, len=(lenx>leny)?lenx:leny, sum="", div=0, x1, y1, rem;
for (var i = 0; i < len; i++) {
x1 = (i >= lenx) ? 0 : parseInt(x[lenx-i-1]);
y1 = (i >= leny) ? 0 : parseInt(y[leny-i-1]);
y1 = (isNaN(y1)) ? 0 : y1;
if (oneNeg) y1 = -y1;
if (borrow) x1 = x1 - 1;
if (y < 0 && x1 > 0 && Math.abs(x1) >= Math.abs(y1)) { borrow=false; div=0; }
if (y < 0 && y1 <= 0 && (x1 < 0 || Math.abs(x1) < Math.abs(y1))) { borrow=true; rem=(x1+y1+div+10)%10; div=10; }
else { rem=(x1+y1+div)%10; div=Math.floor((x1+y1+div)/10); }
sum = Math.abs(rem).toString() + sum;
}
if (div > 0) sum = div.toString() + sum;
sum = parseFloat(sum*10/1000000000);
if (bothNeg || neg) sum = -sum;
return sum;
}
<body>
<p>Click the button to calculate x.</p>
<button onclick="myFunction()">Try it</button>
<br/>
<br/>Enter first number:
<input type="text" id="txt1" name="text1">Enter second number:
<input type="text" id="txt2" name="text2">
<p id="demo"></p>
<script>
function myFunction() {
var y = document.getElementById("txt1").value;
var z = document.getElementById("txt2").value;
var x = +y + +z;
document.getElementById("demo").innerHTML = x;
}
</script>
https://jsfiddle.net/Sanjeevgaut/mtsL1k2x/

Javascript problems with a function not working (it converts fractions into decimals)

Let's say I have a string (like a fraction);
var num = "1/2";
Why does this work:
var y = num.split(' ');
if (y.length > 1) {
var z = y[1].split('/');
var a = (+y[0] + (z[0] / z[1]));
num = a;
} else {
z = y[0].split('/');
if (z.length > 1) {
a = (z[0] / z[1]);
num = a;
}
}
alert(num); //The alert box shows my variable now as a decimal.
And this doesn't:
function parseFractions(x) {
var y = x.split(' ');
if (y.length > 1) {
var z = y[1].split('/');
var a = (+y[0] + (z[0] / z[1]));
x = a;
} else {
z = y[0].split('/');
if (z.length > 1) {
a = (z[0] / z[1]);
x = a;
}
}
}
parseFractions(num); //Here I call my function.
alert(num);
//The alert box does not even show up. The fraction isn't converted into a decimal.
It's basically the same thing, the only difference is that in the 2nd one I tried to make that into a function so I don't have to repeat those lines of code every time I try to convert fractions into decimals.
So what am I doing wrong? Is what I am trying to accomplish possible with a function? Any light into this issue is appreciated!
the value of num is not updated, it is not passed by reference.
function parseFractions(x) {
var y = x.split(' ');
if (y.length > 1) {
var z = y[1].split('/');
var a = (+y[0] + (z[0] / z[1]));
x = a;
} else {
z = y[0].split('/');
if (z.length > 1) {
a = (z[0] / z[1]);
x = a;
}
}
return x;
}
num = parseFractions(num); //set num with the value return from the method
alert(num);
You need to return your value
Add a return to the end of your function
return x;
Adn then call the function with
alert(parseFractions(num)); //Here I call my function.

Categories