Best way to prevent/handle divide by 0 in javascript - javascript

What is the best way to prevent divide by 0 in javascript that is accepting user inputs.
If there is no particular way to achieve this what would be the best way to handle such a situation so as to not prevent other scripts from executing?
Any insights are much appreciated.

There is no way to do that with the normal / and /= operators.
The best way to do what you want is with guards:
function notZero(n) {
n = +n; // Coerce to number.
if (!n) { // Matches +0, -0, NaN
throw new Error('Invalid dividend ' + n);
}
return n;
}
and then do division like
numerator / notZero(denominator)
Alternatively you can always guard the output
function dividend(numerator, denominator) {
var quotient = numerator / denominator;
if (quotient !== quotient) { throw new Error(numerator + " / " + denominator); }
return quotient;
}
but that loses the readability and expressiveness of /=.

Off the top of my head you could:
Check the user input to see if the denominator is zero (or evaluates to zero, depending on what your script actually does).
Check if the result of the action isFinite() and if not then handle appropriately.

what would be the best way to handle such a situation so as to not prevent other scripts from executing
Division by zero doesn't seem to prevent other scripts from execution in JavaScript:
var a = 20;
var b = 0;
var result = a/b;
console.log(result); // returns Infinity
If you want something different to happen in case of division by zero, you could use
function divideIfNotZero(numerator, denominator) {
if (denominator === 0 || isNaN(denominator)) {
return null;
}
else {
return numerator / denominator;
}
}

Hope this is useful
(denominator != 0 ? numerator/denominator : Infinity)
or whatever value you want to put at the end.
Greetings.

To prevent (unwanted) execution
Always verify critical user input and/or results
Use logic and/or callbacks you can prevent to execute
On HTML forms etc. you can use i.e. return false; as value to stop submission.

Why not just check if the denominator is zero?
if(x != 0) z = y / x;
You can also check if the result is Infinity:
3 / 0 == Infinity
Results in true;
(Only tested in chrome.)

A bit different than stopping execution, but the ternary operator is a pretty slick way to customize variable assignment.
var one = 1,
zero = 0,
customValue = 1;
var quotient = zero===0 ? customValue : one / zero;
This way, by setting the customVariable to the integer of your choice, you can expect a predictable result when division by zero occurs.

The best way is contextual. But here's the easiest:
function myFunction( input ){
input = 0 ? 0.0001 : input; // same as if( input == 0 ){ input = 0.0001; }
return 1 / input;
}
Basically if the input is zero, turn it into a very small number before using as a denominator. Works great for integers, since after your division you can round them back down.
A couple caveats prevent this from being universal:
It could cause false positives if your input accepts really small numbers
It won't trigger any error-handling code, if you need to do something special if zero is entered
So it's best for general-purpose, non-critical cases. For example, if you need to return the result of a complex calculation and don't care if the answer is accurate to N digits (determined by 0.0001 vs. 0.00000001, etc.); you just don't want it to break on a divide-by-zero.
As another answer suggested, you could also create a reusable global function.
function divisor( n ){ return ( n = 0 ? 0.0001 : n ); }
function myFunction( input ){ return 1 / divisor( input ); }
Possible improvements:
function divisor( n, orError ){
if( typeof n == 'undefined' || isNaN( n ) || !n ){
if( orError ){ throw new Error( 'Divide by zero.' ); }
return 0.000000000000001;
}else{ return 0 + n; }
}
This would take any value (null, number, string, object) and if invalid or zero, return the failsafe zero-like value. It would also coerce the output to a number just in case it was a string and you were doing something odd. All this would ensure that your divisor function always worked. Finally, for cases where you wanted to handle such errors yourself, you could set the second parameter to true and use a try/catch.

Set a cap on what the value for the numerator can be and set the numerator to that value when the denominator equals 0.

This is a faster approach yet is confusing
let divisor;
let dividend;
let result =(dividend/divisor) || 0
if the result for instance if you are calculating percentage is infinite you can give it 0 as value;

const progress = goal == 0 ? 0 : total/goal

Related

Javascript: How to recursively return a counter?

In the example below, I don't want to make a counter as a param. Rather, I just want to return '+ 1' each time so that what gets returned is the number of steps it takes. My issue lies with the base case. If I do return + 1, I get the correct number of steps plus one additional step so I tried just return but that delivers NaN. Is it even possible?
var numberOfSteps = function(num) {
if (num == 0) {
return;
} else {
if (num % 2 == 0) {
return 1 + numberOfSteps(num/2);
} else {
return 1 + numberOfSteps(num - 1);
}
}
};
edit : The goal is to track how many steps it takes to reduce a number to 0. If it's even, divide by 2 or else subtract by 1. Ultimately, I want to return the number of steps it takes for any given number to get reduced to 0 following those rules
I hope the point has gotten through in the long comment thread and other answers that return + 1 is equivalent to return (+1), that is, return the integer positive one. And since there are no steps to take once you've reached zero, +1 is the wrong answer. Similarly, a plain return is functionally equivalent to return undefined. But undefined is not a number, and you're going to run into problems if you later try to add 1 to it. So the solution from the comments or other answers to return the correct number of steps, which in this case 0, will fix your code.
I would like to point out another way to solve this, though:
const numberOfSteps = (n) =>
n <= 0
? 0
: 1 + numberOfSteps (n % 2 == 0 ? n / 2 : n - 1)
console .log (numberOfSteps (12))
There are superficial differences here from the other solutions, such as using an arrow function, using a conditional statement (ternary) rather than if-statements, and using <= 0 instead of < 0 to avoid possible infinite loops on negative numbers.
But the fundamental difference is that this code only has one recursive branch. I think this is a better match to the problem.
We can think of this as a function which answers "How many steps does it take to reach 0 from our input number if each step cuts even numbers in half and subtracts one from odd ones?" Well that logically leads to a base case (we're already at 0) so have to return 0, and a recursive one (we're at some positive integer) so have to add 1 to the total steps required from our next entry.
By doing this single recursive call and adding one to the result, we make it clearer what the recursion is doing.
If this is unclear, then this alternative might show what I mean:
const takeStep = (n) =>
n % 2 == 0 ? n / 2 : n - 1
const numberOfSteps = (n) =>
n <= 0
? 0
: 1 + numberOfSteps (takeStep (n))
Think you just need to return 0 when it's...zero.
var numberOfSteps = function(num) {
if (num == 0) {
return 0;
} else {
if (num % 2 == 0) {
return 1 + numberOfSteps(num/2);
} else {
return 1 + numberOfSteps(num - 1);
}
}
}
return + 1 maybe doesn't do what you think it does: it returns the number 1. + here means positive not negative, there is no addition or subtraction going on. It will also give you one too many steps.
return; by itself returns undefined, which when converted to a Number, translates to NaN, because, well, it's not a number.

Replace modulus by function

When I try to do 8067 % 80.67 I get 80.66999999999983, instead of 0 beacuse of known floating point javascript behaviour.
So I went and made a function for this, to avoid floating point javascript errors.
function math(a, b) {
var left = Math.abs(a),
times = 1,
abs = a >= 0 ? 1 : -1;
while (Math.abs(a) >= b * times) {
left -= b;
times++;
}
return (a - (b * (times - 1))) * abs;
}
http://jsfiddle.net/s5w3C/
So my question is: is this usefull, ie a good tool to use instead of %? is there cases where this will also give falsy results like the modulus % oprator.
I am looking for a tools to calculate % consistently.
I didn't really inspect the algorithm for correctness, but if you care about efficiency, this is a bad idea. Basically, the larger the input, the slower your code will execute.
I think any fix will only work to a certain level of accuracy and for certain sized numbers. Perhaps something like the following will be sufficient:
function nearlyMod(a, b) {
var precision = ('' + b).split('.').length;
var estimate = (a % b).toFixed(precision);
return estimate == b ? 0 : +estimate;
}
console.log(nearlyMod(8067, 80.66)); // 1
console.log(nearlyMod(8067, 80.67)); // 0
console.log(nearlyMod(8067, 80.68)); // 79.68
It tests if the result is an even divisor within the precision of the original number. If so, it returns 0, otherwise it returns a number to the same precision (which may or may not be what you want).
The result is always a number (the value returned from toFixed is a string, hence +estimate).
A better name might be "roundedMod" or similar.

Comparing negative numbers in JQuery function

I am trying to compare two negative numbers and the comparison is failing. In this specific case, getLeftPercent() is a negative number (-14) yet when comparing, action B is performed. Logically, (-14) is less than (-10) thus action A should be performed.
If I change the right side comparison operand (-10) to a positive number (1 for example) then action A is performed. Is there some quirk of JavaScript that I'm overlooking (which is staring me in the face)? I can post the complete code but there's not really much more.
$(function() {
// the statement in question
if (parseInt(getLeftPercent(), 10) < -10) {
// do action A
// this is just a debug statement
$('#posbanner').html('element position is less than negative 10');
} else {
// do action B
// this is just a debug statement
$('#posbanner').html('element position is greater than or equal to negative 10');
}
});
// element left position on page
function getLeftPercent() {
var leftStr = $('#sidebar').css('left'),
pxPos = leftStr.indexOf('px'),
leftVal = leftStr.substr(0, pxPos),
leftPercent = (leftVal / $(window).width() * 100).toString(),
dotPos = leftPercent.indexOf('.'),
leftPercentStr = dotPos == -1 ? leftPercent : leftPercent.substr(0, dotPos);
return leftPercentStr;
};
I tried running the following code on jsfiddle
if (parseInt( -14, 10) < -10)
{
alert("I am in A");
}
else
{
alert("I am in B");
}
I get I am in A
Not sure, if getLeftPercent() is returning the value you expect.
Your getLeftPercent() function seems way overcomplicated. I'm not sure whether your "left" is relative to the document or parent element, I'll assume document here.
function getLeftPercent() {
'use strict';
return ( ($('#sidebar').offset()).left * 100 / $(window).width() );
}
Most likely your substrings return some characters before the number.
alert(parseInt('-14abc', 10)); // -14
alert(parseInt('abc-14', 10)); // NaN

check whether the number is nearly equal javascript

I want to know whether it is possible?
Let Suppose:
var a = 2592;
var b = 2584;
if(a nearly equal to b) {
// do something
}
Like so.
var diff = Math.abs( a - b );
if( diff > 50 ) {
console.log('diff greater than 50');
}
That would compare if the absolute difference is greater than 50 using Math.abs and simple comparison.
Here's the old school way to do it...
approxeq = function(v1, v2, epsilon) {
if (epsilon == null) {
epsilon = 0.001;
}
return Math.abs(v1 - v2) < epsilon;
};
so,
approxeq(5,5.000001)
is true, while
approxeq(5,5.1)
is false.
You can adjust pass in epsilons explicitly to suit your needs. One part in a thousand usually covers my javascript roundoff issues.
var ratio = 0;
if ( a > b) {
ratio = b / a;
}
else {
ratio = a / b;
}
if (ratio > 0.90) {
//do something
}
One line Es6 way version of The Software Barbarian:
const approxeq = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) <= epsilon;
console.log(approxeq(3.33333, 3.33322)); // true
console.log(approxeq(2.3, 2.33322)); // false
console.log(approxeq(3, 4, 1)); // true
I changed it to include the number in the margin. So with an epsilon margin of 1 approxeq between 1 and 2 is true
Floating point comparison gets complicated in a hurry. It's not as simple as diff less than epsilon in a lot of cases.
Here's an article about the subject, though not javascript specific.
https://floating-point-gui.de/errors/comparison/
TLDR:
When one of the numbers being compared is very close to zero, subtracting the smaller from the larger can lose digits of precision, making the diff appear smaller than it is (or zero).
Very small numbers with different signs work in a weird way.
Dividing by zero will cause problems.
In the article is a function (java) which solves better for these cases:
public static boolean nearlyEqual(float a, float b, float epsilon) {
final float absA = Math.abs(a);
final float absB = Math.abs(b);
final float diff = Math.abs(a - b);
if (a == b) { // shortcut, handles infinities
return true;
} else if (a == 0 || b == 0 || (absA + absB < Float.MIN_NORMAL)) {
// a or b is zero or both are extremely close to it
// relative error is less meaningful here
return diff < (epsilon * Float.MIN_NORMAL);
} else { // use relative error
return diff / Math.min((absA + absB), Float.MAX_VALUE) < epsilon;
}
}
Before you complain: Yes, that's Java, so you'd have to rewrite it in Javascript. It's just to illustrate the algorithm and it's just copied from the article.
I'm still looking for a thorough solution to this problem, ideally with an NPM package so I don't have to figure this out again every time I need it.
Edit: I've found a package which implements the solution from the article linked above (which has the same link in their readme).
https://www.npmjs.com/package/#intocode-io/nearly-equal
This will be a less error-prone solution than others shown in other answers. There are several npm packages which implement the naive solutions which have error cases near zero as described above. Make sure you look at the source before you use them.

Elegant way to bias random boolean

I'd like to create a random boolean in JavaScript, but I want to take the previous value into account. If the previous value was true, I want it to be more likely for the next value to be true. At the moment I've got this (this is in the context of a closure - goUp and lastGoUp are locals to the containing scope):
function setGoUp() {
goUp = getRandomBoolean();
if(lastGoUp) {
goUp = getRandomBoolean() || goUp;
}
else {
goUp = getRandomBoolean() && goUp;
}
lastGoUp = goUp;
}
So, the algorithm goes:
Get a random boolean
If the random boolean from the previous call was True:
a) get another random boolean, and or these two together
b) else get another random boolean and and these together.
I'm sure this algorithm could be simplified. I wondered about doing:
if(lastGoUp && goUp) {
goUp = goUp * (getRandomBoolean() || goUp);
}
but that seems really dirty.
There's also a problem with this algorithm which means that I can only double the chance of getting the same boolean again - I can't tweak it easily. Any ideas?
You should define the distribution you want, but maybe you are looking for the following?
if (lastGoUp) {
goUp = Math.random() < 0.8;
} else {
goUp = Math.random() < 0.2;
}
Instead of getting a random boolean, get a random number, say between 0 and 99. Keep a threshold value instead of the last number, and adjust the threshold according to the result:
var threshold = 50;
function setGoUp() {
goUp = getRandomNumber() < threshold;
threshold += goUp ? -10 : 10;
}
This would keep a running tab, so if you get consecutive results that are the same, the probability would keep falling for that result.
If you only want to consider the last result, you would instead set the threshold to a specific value:
threshold = goUp ? 40 : 60;
If you only want the probability of the next event to depend on the current value, and not the history of values up til now, what you want is called a Markov process. Often these are implemented with a 2D table of probabilities that you look up (prob of each next outcome given current one), but for a simple bool-valued event, an if statement is sufficient (see meriton's answer; note that it corresponds to a table of probabilities [0.8 0.2; 0.2 0.8]).
If you want something that gets more likely, say, the more successes you get in a row, then you need to devise a sequence of probabilities for success that perhaps approaches, but does not exceed, 1. There are any number of formulas which can do this, depending on how strong you want the bias to become and how quickly you want it to get there.
I would just make the probability of getting value true be an explicit float variable p. Then I could tweak it easily, by increasing p in some way if I got true last time or by doing nothing with it if I got 'false'.
Can replace Math.random for a better randomizer.
var setGoUp = (function(){
var last;
return function(){
// if last 66% chance for true else 50% chance of true.
return !!(last ? Math.random()*3 : Math.random()*2);
}
}());
!! converts anything to a boolean, 0 = false.

Categories