My first day of Javascript and I am incredibly confused. I am passing numbers returned from a form to a function, but the result is not consistent with what it should be. My testing leaves a lot to be desired, but hopefully the following makes sense.
The function g calculates the sum of the sequence.
<form name="gaussform">
<input name="min"
type="number"
min="1"
value="1">
<input name="max"
type="number"
min="2"
value="10">
<input name="step"
type="number"
min="1"
value="1">
<input onclick="alert_g()"
type="submit"
value="calculate">
</form>
<script type="text/javascript">
function g(min,max,step) {
var actualmax = max - ((max - min) % step)
return (min + actualmax) * ((1 + ((actualmax - min) / step)) / 2)
}
function alert_g() {
var frm = document.forms["gaussform"]
var min = frm["min"].value
var max = frm["max"].value
var step = frm["step"].value
if (min == 1) {
alert("min is 1")}
if (max == 10) {
alert("max is 10")}
if (step == 1) {
alert("step is 1")}
alert(g(min,max,step))
// below returns the desired result
alert(g(1,10,1))}
</script>
the if statements are only so I can understand what is going on!
So if the user enter 1,10,1 (the default values) the result should be 55.
alert(g(1,10,1)) -> 55
alert(g(min,max,step) -> 550
alert(g(1,100,2)) -> 2500
alert(g(min,max,step) -> 4975 (obviously min,max,step == 1,100,2)
the function g is correct, but I do not understand what is happening to the values that are being passed to it.
This expression...
min + actualmax
...is the problem.
You probably want to make that...
+min + +actualmax
...or use parseFloat(), parseInt() or whatever suits your requirements to turn those strings into an actual Number.
jsFiddle.
JavaScript's + operator is overloaded for arithmetic addition and string concatenation. Because user input is always a string, you're doing string concatenation.
The values you use in your function are strings (every value returned by a form will be a string). You need to convert them to number to get the good result. This can be done with parseFloat function.
parseFloat('5') // return 5
parseInt can also be used if you want an Integer (no floating point number e.g.: 1.3), but be sure to set the radix parameter in order to always get consistent results.
parseInt('5', 10) // return 5
This can be confusing because Javascript use the + symbol for addition and concatenations of strings (which is . sign in PHP for example). As so, it's hard for the javascript engine to know how a value is expected to be converted.
By the way, you can always use typeof operator to checkout the type of a variable. For example:
typeof '5' // ouput: String
typeof 5 // output: Number
alert(g(parseInt(min),parseInt(max),parseInt(step))) has solved it!
But apparently this is bad form. See comments...
alert(g(parseInt(min,10),parseInt(max,10),parseInt(step,10))) perhaps?
Related
I am trying to solve a kata that seems to be simple on codewars but i seem to not be getting it right.
The instruction for this is as simple as below
Given the string representations of two integers, return the string representation of the sum of those integers.
For example:
sumStrings('1','2') // => '3'
A string representation of an integer will contain no characters besides the ten numerals "0" to "9".
And this is what i have tried
function sumStrings(a,b) {
return ((+a) + (+b)).toString();
}
But the results solves all except two and these are the errors i get
sumStrings('712569312664357328695151392', '8100824045303269669937') - Expected: '712577413488402631964821329', instead got: '7.125774134884027e+26'
sumStrings('50095301248058391139327916261', '81055900096023504197206408605') - Expected: '131151201344081895336534324866', instead got: '1.3115120134408189e+29'
I don't seem to understand where the issues is from. Any help would help thanks.
The value you entered is bigger than the int type max value. You can try changing your code to:
function sumStrings(a,b) {
return ((BigInt(a)) + BigInt(b)).toString();
}
This way it should return the right value
You could pop the digits and collect with a carry over for the next digit.
function add(a, b) {
var aa = Array.from(a, Number),
bb = Array.from(b, Number),
result = [],
carry = 0,
i = Math.max(a.length, b.length);
while (i--) {
carry += (aa.pop() || 0) + (bb.pop() || 0);
result.unshift(carry % 10);
carry = Math.floor(carry / 10);
}
while (carry) {
result.unshift(carry % 10);
carry = Math.floor(carry / 10);
}
return result.join('');
}
console.log(add('712569312664357328695151392', '8100824045303269669937'));
console.log(add('50095301248058391139327916261', '81055900096023504197206408605'));
The problem is that regular javascript integers are not having enough space to store that much big number, So it uses the exponential notation to not lose its precision
what you can do is split each number into parts and add them separately,
one such example is here SO answer
My solution is:
function sumStrings(a,b) {
return BigInt(a) + BigInt(b) + ''
}
Converting from a string to a number or vice versa is not perfect in any language, they will be off by some digits. This doesn't seem to affect small numbers, but it affects big numbers a lot.
The function could go like this.
function sumStrings(a, b) {
return (BigInt(a) + BigInt(b)).toString() // or parseInt for both
}
However, it's still not perfect since if we try to do:
console.log((4213213124214211215421314213.0 + 124214321214213434213124211.0) === sumStrings('4213213124214211215421314213', '124214321214213434213124211'))
The output would be false.
When I run this function with the first radio button selected, the system outputs the correct value of 30. However, once I try to apply some changes to this value (for example by adding 1 to this value of 30) the system shows me 301 as a result.
I get the same issue when the radio button with value 25 is selected. Once I try to do mathematical changes, the system treats this variable as 250.
Any ideas what I am missing here? Thanks in advance.
<script>
function f1()
{
...
var Ergebnis_RP = document.getElementsByName("Ergebnis_RP");
if(Ergebnis_RP[0].checked)
{ var Erg = Ergebnis_RP[0].value;}
else if(Ergebnis_RP[1].checked)
{ var Erg = Ergebnis_RP[1].value;}
...
document.write(Erg);
var Spielwert = Erg + 1;
document.write(Spielwert);
}
</script>
<body>
<input type="radio" name="Ergebnis_RP" value=30>Verl. Schwarz
<input type="radio" name="Ergebnis_RP" value=25>Verl. U3
</body>
The value of a textbox is always a string. You need to coerce it to a number. The easiest way to do that is:
+Ergebnis_RP[0].value
Be sure to do this every time you read a number from a textbox.
Further explanation of the issue:
When you combine two strings, they are concatenated like "ab" + "cd" -> "abcd".
But when you combine different types, the second one is coerced to be the same as the first. "ab" + 1 -> "ab" + "1" -> "ab1".
Your code takes a string and adds a number. The string happens to be digits but that doesn't matter. "12" + 3 -> "12" + "3" -> "123".
To fix this, start with a number then add the string. 0 + "12" -> 0 + 12 -> 12.
As a shortcut, the + operator acts on numbers just like the - operator. Consider the number -5. The - is a negation. + is another unary operator that takes a number and returns the same number. Sounds useless, but it has its place. +"12" -> 12.
I have a simple input field with type set to number. This will be used to enter input in [0,255] range (for RGB).
<input type="number" id="inputBox" min="0" max="255" step="1" />
In its current form, this input field will accept the following values:
012 // zero prefixed numbers
1.0 // floating-point
.1 // floating-point
-5 // range underflow
300 // range overflow
I want it to accept only the integers in the range of [0,255]. So, no zero prefix, no floating-point numbers.
I've solved the range problem using input event:
inputBox.addEventListener("input", function () {
if (this.validity.rangeUnderflow) {
this.value = this.min;
}
else if (this.validity.rangeOverflow) {
this.value = this.max;
}
});
and floating-point problem using keydown event (by not allowing .):
inputBox.addEventListener("keydown", function (e) {
if (!isFloat(this.step)) {
if (e.key == ".") {
e.preventDefault();
}
}
});
function isFloat(f) {
var f = parseFloat(f);
var floor = Math.floor(f);
var fraction = f - floor;
if (fraction > 0) {
return true;
}
return false;
}
I'm stuck at solving the zero prefixed numbers problem. I can use the following line of code in the input event to remove zero prefix
this.value = this.valueAsNumber; // or parseInt(this.value, 10)
which is working fine, but this kind of breaks the input field's functionality. I can't enter values with E notation. In my case, I don't need to, but I might somewhere else. As soon as I enter 1e, it evaluates to NaN, and is assigned back to input field.
Is there a way to make these both work?
JSFiddle
I just worked on a problem like this. It's super easy to do:
inputBox.addEventListener("keydown", function (e) {
if (!isFloat(this.step)) {
if (e.key == ".") {
e.preventDefault();
}
}
while ( this.value.toString()[0] === "0" && this.value.length > 0){
this.value = this.value.toString().slice(1);
}
});
Note that the value of the field might change in ways other than keydown events, suck as paste. So I would put these checks in a function, validationCheck, and run that function for each relevant event, including the catchall- onchange.
You can use a regular expression such as:
<input type="text" pattern="0|[1-9]\d*">
this will gives you a string representation of a positive whole number without prefixed zeros.
You then have to test with JavaScript if the value is less than or equals 255.
Here is a JSFiddle.
String with only multiple zeros are not accepted.
The last days I read how NaN always compares false even with itself and how to compare stuff when NaN may occur, and now I made a JS that compares two NaN true. WTF? Or did I compare 'NaN' strings?
http://www.bksys.at/bernhard/JS-NaN-compare-true.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>radioactivity calculator</title>
</head>
<body>
<form name="form1">
a: <input type="text" name="a"><br>
b: <input type="text" name="b"><br>
x: <input type="text" name="x"><br>
</form>
<script type="text/javascript">
document.form1.a.value=Math.sqrt(-1);
document.form1.b.value=(1/0)/(1/0);
document.form1.x.value=(document.form1.a.value==document.form1.b.value);
</script>
</body>
</html>
You are indeed comparing the string "NaN" against another string "NaN", which equates to true. The value held in text input elements is always pulled as a String type.
A simple way to resolve this is to prefix your values with the Unary Plus (+) operator to convert them to integer values (you can drop those brackets, too):
document.form1.x.value = +document.form1.a.value == +document.form1.b.value;
Example
document.form1.a.value = Math.sqrt(-1);
document.form1.b.value = (1/0) / (1/0);
document.form1.x.value = +document.form1.a.value == +document.form1.b.value;
<form name="form1">
a: <input type="text" name="a" size="20" value="a"><br>
b: <input type="text" name="b" size="20" value="b"><br>
x: <input type="text" name="x" size="20" value="x"><br>
</form>
Note: As RobG pointed out in his comment below it's important to note here that converting the string value "NaN" to an integer with the Unary Plus operator converts it directly to NaN because the string cannot be replicated as a numeric value. The same would happen if both of your input elements contained the value "Foo" - or even contained two completely different non-numeric string values. Whilst this solution does work, it may yield undesired results if you are to extend this code to handle non-numeric values as well.
This is a JavaScript gotcha ;)
The proper way to compare NaN is to use the isNaN method.
var a = 'a' + 5; //NaN
if (isNaN(a)) {
//do something
}
NaN is a special value in JavaScript. It doesn't even equal itself (also a quick way to test):
var a = parseInt('seven');
if (a == a) {
alert("a == a");
} else {
alert("a != a"); // This will happen
}
if (a == 'NaN') {
// Won't happen
} else {
alert("NaN is not equal to the string 'NaN'"); // Here
}
http://jsfiddle.net/u951v90o/
I did a rewrite of the code I submitted yesterday based on suggestions from others. I now have this but still can't seem to get it to work with greater than less than. I can add/substract the 2 numbers and get a valid answers. I can't get a > < to work however. Hoping someone can offer some additional help keeping it within this format of "If statements".
if ((input.search("what is greater")!= -1) && (input.search(/\d{1,10}/)!=-1) && (input.search(/\d{1,10}/)!=-1))
{var numbersInString = input.match(/\d+/g);
var num1 = parseInt( numbersInString[0], 10 );
var num2 = parseInt( numbersInString[1], 10 );
if (num1 < num2) document.result.result.value = ""+num1+" is less than "+num2+"";
if (num1 > num2) document.result.result.value = ""+num1+" is greater than "+num2+"";
if (num1 = num2) document.result.result.value = "Both numbers are equal";
return true;}
It sounds like you want to manipulate a number in two ways:
1) You want to refer to the individual characters.
2) You want to compare the number to another number and see if one is greater than another.
If you have a string called input, then you can use the function parseInt(input, 10) to convert it from a string to the number represented by that string.
If you want to get just the first two characters, you can use the substring function.
The important thing to keep in mind is that to the computer, the string '12345' and the number 12345 are completely different. The computer has a completely different set of operations that it will perform on each.
also, #albin is correct to point out that putting semicolons after your if statements is wrong.
The output of the match method is an array of strings, so I think you are NOT comparing numbers but strings. Try doing this before comparing your numbers.
var num1 = parseInt( numbersInString[0], 10 );
var num2 = parseInt( numbersInString[1], 10 );
And then compare num1 and num2.
http://jsfiddle.net/qt3RW/
Simple input box:
<input id="input1" value="Is 6 greater than 5"></input>
Parser find 'Is # greater than #' where # is digit and alert this digits:
var IsStringValid = $("#input1").val().match(/Is \d greater than \d/g);
alert(IsStringValid);
if(IsStringValid){
var values = $("#input1").val().match(/\d/g);
for(var i = 0; i < values.length; i++){
alert(values[i])
}
}