Elegant way to bias random boolean - javascript

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.

Related

Theoretical analysis of the algorithm that returns true or false, given a probability

I want to implement a method that returns true with a probability of n/m and returns false with a probability of (m-n)/m.
For example, I want to get true with a probability of 7/10000.
To achieve this, I first get a random integer n that is under 10000 from the function getRandomIntUnderN. Then, I judge whether n is smaller than (7+1), if it is, I return true, false if not.
I have an implementation below:
// 0 is included while n is not
const getRandomIntUnderN = (n) => {
const rn = Math.random() * n
return Math.trunc(rn)
}
// the opportunity of a truthy return value is n/m
const goAtChance = (n, m) => {
return getRandomIntUnderN(m) < n
}
// a opportunity of 7‰ to return true
console.log(goAtChance(7, 10000))
My question is: is it okay that I just judge whether n is under (7+1) to make a perfect probability as expected?
On one hand, numbers from 1 to 7 are not distributed discretely enough in the range from 1 to 10000: it seems there will be a bias that makes it unlikely to return a truthy value.
On the other hand, since I can get a purely random number from getRandomIntUnderN, the chance will not be affected by which numbers I choose to determine the return value. It can be [1,2,3,4,5,6,7], [21,22,23,24,25,26,27], [23,55,3,66,762,92,123] or whatever under 10000.
So, which opinion is right?
Then, I judge whether n is smaller than (7+1), if it is, return true, false if not.
This is not how you implemented it. Your code checks that n is less than 7, which is the correct way to do it.
it seems there will be a bias that makes it unlikely to return a truthy value.
Where does that statement come from? Surely you can test this premise... and see how likely it is.
the chance will not be affected by which numbers did I choose to determine the return value
This is true.
How to test
You can easily test what the distribution is of your implementation. You can call the function repeatedly and keep a record of the results you get, and see how that evolves over time. In statistics you get more reliable results the greater the size of your sample is.
Here is a snippet that keeps executing the goAtChance function and records the total number of calls and the number of true results. Every 10 milliseconds the results are updated on the page, including the ratio of the number of true over the total number. This ratio should over time converge to 0.0007 if all is well.
const getRandomIntUnderN = (n) => Math.floor(Math.random() * n);
const goAtChance = (n, m) => getRandomIntUnderN(m) < n;
let [outTotal, outHits, outRatio] = document.querySelectorAll("span");
let hits = 0; // Number of results that are true
let total = 0; // Total number of results
requestAnimationFrame(function loop() {
let deadline = performance.now() + 10;
do {
hits += goAtChance(7, 10000); // boolean coerces to 0 or 1
total++;
} while (performance.now() < deadline);
// Show the accumulated results
outTotal.textContent = total;
outHits.textContent = hits;
outRatio.textContent = (hits / total).toFixed(8);
requestAnimationFrame(loop); // Allow screen to update and then continue
});
Samples: <span></span><br>
Hits: <span></span><br>
Ratio: <span></span>

mathematical value transformation / switch behavior in js

I use common functions like map() and clamp() to transform values.
I wonder if there is a similar mathematical function which lets me translate a rising value to an on and off state (0 and 1).
Could a square wave help?
For more context: I want the value to be 1 whilst something is animating and 0 after it finished. The input value is clamped, the functionality of the function I'm looking for is like a switch. It would be a substitute for a complex if statement. Executed in a loop I'm trying to save resources by not using performance heavy if statements.
Looking forward to your input!
This is what I came up with in the end. Not sure if this is helpful to anyone else. It converts any value between 0 and 1 to 1.
But if the input value is equal to 0 or the input value is equal to 1, the function will return 0 as well.
Resulting in the loopback / switch behavior.
It returns 1 only whilst a value is progressing.
Hope this makes sense and is correct. Happy to hear your thoughts.
Also happy to hear some further thoughts on if such a function is more performant than an if-statement.
In the end I had to solve this to prove to myself that it's possible to do with math. (of course it is):)
const loopback = (i, m = 100) => {
//returns 1 while value is progressing, returns 0 if value is 0 or 1
//based on triangle wave function: https://discourse.processing.org/t/sawtooth-wave-algorithm/27433
i = clamp(i) //normalize value to 0-1
return Math.ceil(Math.abs((i*(m)) % (m)) / m)
}
const clamp = (number, min = 0, max = 1) => {
return Math.max(min, Math.min(number, max));
}
//in my usecase, this is an alternative to following condition:
/*if(i >= 1 || i <= 0) {
return 0;
} else {
return 1;
}

Javascript Help - selfDividingNumbers Algorithm producing all 0's

Greetings Stack Overflow!
First off, this is my first question!
I am trying to solve the selfDividingNumbers algorithm and I ran into this interesting problem. This function is supposed to take a range of numbers to check if they are self dividing.
Self Dividing example:
128 is a self-dividing number because
128 % 1 == 0, 128 % 2 == 0, and 128 % 8 == 0.
My attempt with Javascript.
/*
selfDividingNumbers( 1, 22 );
*/
var selfDividingNumbers = function(left, right) {
var output = [];
while(left <= right){
// convert number into an array of strings, size 1
var leftString = left.toString().split();
// initialize digit iterator
var currentDigit = leftString[0];
for(var i = 0; i < leftString.length; i++){
currentDigit = parseInt(leftString[i])
console.log( left % currentDigit );
}
// increment lower bound
left++;
}
return output
};
When comparing the current lower bound to the current digit of the lower bound, left % currentDigit it always produces zero! I figure this is probably a type error but I am unsure of why and would love for someone to point out why!
Would also like to see any other ideas to avoid this problem!
I figured this was a good chance to get a better handle on Javascript considering I am clueless as to why my program is producing this output. Any help would be appreciated! :)
Thanks Stack Overflow!
Calling split() isn't buying you anything. Remove it and you'll get the results you expect. You still have to write the code to populate output though.
The answer by #Joseph may fix your current code, but I think there is a potentially easier way to go about doing this. Consider the following script:
var start = 128;
var num = start;
var sd = true;
while (num > 0) {
var last = num % 10;
if (start % last != 0) {
sd = false;
break;
}
num = Math.floor(num / 10);
}
if (sd) {
print("Is self dividing");
}
else {
print("Is NOT self dividing");
}
Demo
To test each digit in the number for its ability to cleanly divide the original number, you can simply use a loop. In each iteration, check num % 10 to get the current digit, and then divide the number by ten. If we never see a digit which can not divide evenly, then the number is not self dividing, otherwise it is.
So the string split method takes the string and returns an array of string parts. The method expects a parameter, however, the dividing element. If no dividing element is provided, the method will return only one part, the string itself. In your case, what you probably intended was to split the string into individual characters, which would mean the divider would be the empty string:
var leftString = left.toString().split('');
Since you are already familiar with console.log, note that you could also use it to debug your program. If you are confused about the output of left % currentDigit, one thing you could try is logging the variables just before the call,
console.log(typeof left, left, typeof currentDigit, currentDigit)
which might give you ideas about where to look next.

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.

Best way to prevent/handle divide by 0 in 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

Categories