I found a very strange issue, the issue is the ROUND method in PHP and Javascript the calculation results are not the same!?
See the following example:
PHP
echo round(175.5); // 176
echo round(-175.5); // -176
Javascript
console.log(Math.round(175.5)); // 176
console.log(Math.round(-175.5)); // -175 <-why not -176!!??
anyone know why? and how to make Javascript and PHP the same results?
That's not an issue, it is well documented
If the fractional portion is exactly 0.5, the argument is rounded to
the next integer in the direction of +∞. Note that this differs from
many languages' round() functions, which often round this case to the
next integer away from zero, instead (giving a different result in the
case of negative numbers with a fractional part of exactly 0.5).
If you want the same behaviour on Javascript, I would use
var n = -175.5;
var round = Math.round(Math.abs(n))*(-1)
A quick solution is to do the following:
echo round(-175.5, 0, PHP_ROUND_HALF_DOWN); // -175
There are other modes to choose from:
PHP_ROUND_HALF_UP - default
PHP_ROUND_HALF_EVEN
PHP_ROUND_HALF_ODD
See the documentation for more information.
This function will behave the same as in javascript:
function jsround($float, $precision = 0){
if($float < 0){
return round($float, $precision, PHP_ROUND_HALF_DOWN);
}
return round($float, $precision);
}
console.log(Math.round(175.5)); // 176
console.log(Math.round(-175.5)); // -175 <-why not -176!!??
175.5 its round value 176 it's value increasing.
-175.5 round value is -175. Because when I round -175.5 then it also increasing that means -175>-176.
To control it more use ceil and floor for rounding. That way you can choose which way to round
Or... if you wanted JavaScript to behave the same as PHP, use this:
function phpRound(number) {
if(number < 0)
return 0 - Math.round(0 - number);
return Math.round(number);
}
Related
I am building a factorization program and I would like to change each BigInt type to regular Numbers when number <= Number.MAX_SAFE_INTEGER.
Instead of coding two functions for each case, it would be nice if I could keep it all into one function which could vary variables types accordingly (something like let myVar = 3n || 3 I guess).
function Factorize(dividend) {
let divisor = 2n;
//if number <= Number.MAX_SAFE_INTEGER then let divisor = 2. Same for all other bigInts.
let method1 = [], method2 = [];
while (dividend > 1n) {
if (dividend % divisor === 0n) {
method1.push(`${divisor}`);
method2.push(`${dividend} / ${divisor}`);
dividend /= divisor;
} else {
divisor++
};
};
return {
default: method1,
detailed: method2,
get isPrime() {
return this.default.length === 1 && this.default[0] !== 2;
}
};
};
const number = parseInt(prompt());
console.log(Factorize(BigInt(number)));
Thanks for your help.
What's the difficulty? Your comment contains half the required code already:
if (dividend <= Number.MAX_SAFE_INTEGER) {
divisor = 2;
dividend = Number(dividend);
}
And then you only need to replace the two strict equality comparisons === 0n and !== 2 with their non-strict variants. 0 == 0n returns true, 0n === 0n returns false.
Some other things worth mentioning:
(1) This method for factorization is extremely slow. There are prime numbers well below Number.MAX_SAFE_INTEGER for which this will take months. Depending on your use case, limiting the input size or implementing some sort of timeout (e.g., returning an error if a certain number of iterations wasn't enough to find the complete result) may be more important than supporting BigInts at all. (For inputs that have only small prime factors, even extremely huge inputs will still terminate quickly, so it's certainly possible to exceed Number range (even Number.MAX_VALUE) while still only taking a few milliseconds.)
(2) Using parseInt to get your input means that you're limiting yourself to Number precision; converting that Number to a BigInt afterwards doesn't bring the lost bits back. For example, if someone enters '12157665459056928801' (which is 3n ** 40n), parseInt will truncate that and your program will hence compute the wrong result. To avoid that, use the fact that the BigInt() constructor can convert strings directly, i.e.: BigInt(prompt()).
(3) While it's sometimes possible to write code that can work on both Numbers and BigInts, doing so is generally not recommended (and often not even useful), because the two types of values (intentionally!) behave differently in a number of ways (otherwise we wouldn't need both of them), so there is a large risk of such code not doing what you think it'll do. In this particular case it should be okay; I'm just advising not to generalize from this example.
Let me be brief. I'm trying to calculate
alert((Math.pow(7,35))%71)
but it gives me 61, when the result must be 70. What's wrong?
As others mentioned before with regards to using Math.pow(7,35), this resulting number is way too big for Javascript to handle.
To resolve your problem you need to use an external javascript library.
(Or write your own ;) )
Here are some examples of Javascript libraries that handle big numbers.
BigNum
Bignumber
I hope it helps.
The number you're using is too big for javascript. The max size of an int is 2^53 -- which is less than 7^35.
The only value which requires more precision is an intermediate result. So the problem can also be avoided without the need for higher precision variables when you have an algorithm that doesn't need the problematic intermediate result.
The following formula can be useful for that:
(a.b) % c = (a % c)(b % c) % c
This means Math.pow(7,35)%71 = ((Math.pow(7,17)%71) * (Math.pow(7,18)%71)) % 71.
Now the intermediate results are smaller, but might still be too big. So we need to split up further and to apply the modula operator on smaller intermediate results.
So you can do something like this:
Math.pow((Math.pow(7,7)%71),5)%71
But you probably need to do this for integer numbers wich are variable (otherwise, you could have avoided the problem by hardcoding the result).
So, you need to have an idea about the range of values you can expect and to define an algoritm that splits up the power calculation into pieces that will always have results that are small enough when the input is within the expected range.
And whatever you choose for a calculation like this, calculation with higher precision variables (using a specialized library) or a specilized algoritm, you should always assert the input to make sure your calculation returns a value only when you are sure it can deliver a correct value. Otherwise your implementation becomes unreliable for anyone who isn't aware of the range in which it is valid. Otherwise return an exception with a message that tells clearly which input or combination of inputs is the problem and why.
I have a JavaScript calculator which uses the Math.cbrt() function. When I calculate the cube root of 125 it returns 4.999999999999999. I understand that I could use Math.round() to round any answers that this function returns to integer values, but I do not want to do that exactly. Is there a way to use this if and only if the result of calculation is some number followed by a string of 9s (or something similar like 4.99999998 perhaps) after the decimal?
What you are dealing with is the frustration of floating point numbers in computing. See the Floating Point Guide for more information on this critical topic.
The short version:
Certain non-integer values cannot be represented accurately by computers, so they store a value that is "near enough". Just try evaluating 3.3 / 3 in your favourite REPL.
Say what?!
Computers are supposed to be perfect at this numbers/math thing, right? Can I trust any answer they give me?
Yes, for integers, they are pretty much perfect. But for non-integer calculations, you should assume that answers won't be exact, and account for these floating point errors.
The solution in Javascript
In newer versions of Javascript, you have a defined constant Number.EPSILON, which is the smallest difference between the actual number and the approximation that it can actually store.
Using this, you can multiply that constant by the result you get and add it to the result and you should get the exact value you require.
function cbrt(n) {
return Math.cbrt(n) + (Number.EPSILON * Math.cbrt(n));
}
Alternatively, you can use the rounding behaviour of the .toFixed() method on numbers together with the parseFloat() function if you only care about numbers up to a certain number of decimal places (less than 20).
function num(n, prec) {
if (prec === void 0) prec = 8; // default to 8 decimal places
return parseFloat(n.toFixed(prec));
}
var threshold = 0.999; // set to whatever you want
var fraction = result % 1;
if (fraction >= threshold) {
result = Math.round(result);
}
I am trying to generate randomly basic math operations(addition, subtractions, multiplication and division) and sometime my function returns NaN.
I used function parseInt(), but I still have the same problem. I will appreciate if anybody can help me with any suggestion.
Thank you in advance!
Here is my code:
function randNum(min,max)
{
var num = min+Math.floor((Math.random()*(max-min+1)));
return num;
}
var choose, operator, firstNum, secondNum,rightAnswer;
function getProb()
{
var chooseOp=randNum(1,4);
choose=parseInt(chooseOp);
if (choose==1)
{
oprator="+";
var choose1=randNum(0,10);
var choose2=randNum(0,10);
firstNum=parseInt(choose1);
secondNum=parseInt(choose2);
document.getElementById("mathProb").innerHTML=firstNum+operator+secondNum+"=";
rightAnswer=choose1 + choose2;
}
else if (choose==2)
{
operator="-";
var choose1=randNum(0,10);
var choose2=randNum(0,10);
firstNum=parseInt(choose1);
secondNum=parseInt(choose2);
document.getElementById("mathProb").innerHTML=firstNum+operator+secondNum+"=";
rightAnswer=firstNum - secondNum;
}
else if (choose==3)
{
operator="x";
var choose1=randNum(0,10);
var choose2=randNum(0,10);
firstNum=parseInt(choose1);
secondNum=parseInt(choose2);
document.getElementById("mathProb").innerHTML=firstNum+operator+secondNum+"=";
rightAnswer=choose1 * choose2;
}
else if (choose==4)
{
operator="/";
var choose1=randNum(0,10);
var choose2=randNum(0,10);
firstNum=parseInt(choose1);
secondNum=parseInt(choose2);
document.getElementById("mathProb").innerHTML=firstNum+operator+secondNum+"=";
rightAnswer=choose1/choose2;
}
}
When choose==1, operator is misspelled as oprator. If you correct it, problem is solved
http://jsfiddle.net/uERwd/2/
UPDATE:
Your code can be made shorter as: http://jsfiddle.net/uERwd/3/
Your division operation has the possibility of dividing by zero, which would return NaN.
Your "NaN" bug is here :
rightAnswer=choose1/choose2;
choose1 an choose2 are integer in [0, 1].
One time over 121, you're dividing 0 by 0, wich gives NaN.
And a little less than one time over 11, you're dividing a not null number by 0, wich gives Infinity.
You need to specify with a number that represent numeral system, tipically, base 10
http://www.w3schools.com/jsref/jsref_parseint.asp
Add the number 10 to the function call like this
firstNum = parseInt(choose1, 10);
When you randomly choose the division operator, it's possible to have zero come out for both choose1 and choose1, which means you attempt to evaluate rightAnswer = 0 / 0;. In Javascript, this equals NaN. Additionally, and this should happen more often, if you choose zero in the denominator any other number in the numerator the answer will come out as Infinity. Of course, zero over anything is zero.
It's a simple syntax error:
oprator="+"; // should be `operator`
That's why this statement...
firstNum+operator+secondNum+"=";
... will actually be evaluated as ...
firstNum+undefined+secondNum+"=";
The first pair will give you NaN, NaN + Number will be a NaN again, and NaN + String ("=") will result in NaN converted to string, then appended with '=' (hence resulting 'NaN=').
I'd strongly recommend placing "use strict"; line at the beginning of your scripts to catch such errors. With this, you'll get an error:
ReferenceError: assignment to undeclared variable oprator
... and won't need to make SO parse your script for errors instead. )
Sidenotes, I have plenty of them:
your randNum function will return you a Number, so no need to use parseInt (you may have to convert arguments of this function, but even that seems not to be necessary here) on its result;
if you divide by zero, you get Infinity; if you divide zero by zero, you get NaN as a result; be prepared or adjust the minimums. )
you violate DRY principle, repeating most of the statements outputting a result, why don't convert them into a function? Check this snippet (started by #sv_in, completed by me) for example how to do it.
How can I round the number using jQuery?
If the number is 3168 I want to print it as 32.
Or if the number is 5233 the result should be 52.
How can I do that?
Should I use the Math.round function?
Yes, you should use Math.round (after dividing by 100).
jQuery is a library for DOM traversal, event handling and animation built on top of JavaScript. It doesn't replace JavaScript and doesn't reimplement all its basic functions.
var num = 3168;
$('#myElement').text(Math.round(num/100));
I assume you mean divide by 100, then round? Or did you mean to have decimal places? (In which case, remove the /100 portion)
Also, this is just basic JavaScript. As another user mentioned, jQuery is to work with the document itself, not to perform math operations.
And here is a snippet from the jQuery math library1:
(function($){
$.round = Math.round;
})(jQuery);
$.round(3168 / 100) // 32
$.round(5233 / 100) // 52
1 Meant for humor only--this kind of functionality is provided out-of-the-box by JavaScript itself.
<script type='text/javascript'>
function jqROund(a) {
return Math.round(a/100);
}
</script>
<input type='text' id='numba' value='3168'>
<input type='button' onclick="alert( jqRound($('#numba').val() ) );">
The Math.round method does exactly you want and does not only ceil, or floor. It will round it to the nearest Integer.
If you're using the javascript Number object you can use the toFixed() method. I'm assuming those numbers are missing the decimal point. If not, divide by 100 and as above.
You can use this one :) roundMe(1.2345, 4)
function roundMe(n, sig) {
if (n === 0) return 0;
var mult = Math.pow(10, sig - Math.floor(Math.log(n < 0 ? -n: n) / Math.LN10) - 1);
return Math.round(n * mult) / mult;
}