What is the percent change of this code reaching the number 200, 500 and 1000?
I created this code for 200 to be 50% but it keeps rolling numbers above 200, someone please help me if you understand :D.
var mainMultplier = 100;
var numerator = 99;
var denominator = 100;
for(;;) {
var randomInt = random.real(0, 1.0);
if ( numerator/denominator > randomInt ) {
numerator = numerator + 1;
denominator = denominator + 1;
mainMultplier = mainMultplier + 1;
} else {
break;
}
}
Edit
Based on the code you have posted, we can see these two base rules:
P(100) = 1 - 0.99 = 0.01
P(101) = (1 - P(100)) * (1 - (100 / 101)) = P(101) = (1 - P(100)) * (1 / 101)
The second rule can be generalized for any number X after 100:
P(X) = (1 - P(X - 1)) * (1 / X)
Now, I did learn how to do proofs by induction at Uni, which I'm sure would help my explanation here, but I can't remember it anymore :(. So instead, I've written some code to generate a lookup table p, from 100 to 1000:
var p = [];
p[100] = 0.01;
for (var x = 101; x <= 1000; x++)
p[x] = (1 - p[x - 1]) * (1 / x);
Edit 2
And that's as far as my help can go. You may want to post the generalized algorithm on the Software Engineering page.
Related
I have asked a question very similar to this so I will mention the previous solutions at the end, I have a website that calculates π with the client's CPU while storing it on a server, so far I've got:
'701.766.448.388' points inside the circle, and '893.547.800.000' in total, these numbers are calculated using this code. (working example at: https://jsfiddle.net/d47zwvh5/2/)
let inside = 0;
let size = 500;
for (let i = 0; i < iterations; i++) {
var Xpos = Math.random() * size;
var Ypos = Math.random() * size;
var dist = Math.hypot(Xpos - size / 2, Ypos - size / 2);
if (dist < size / 2) {
inside++;
}
}
The problem
(4 * 701.766.448.388) / 893.547.800.000 = 3,141483638
This is the result we get, which is correct until the fourth digit, 4 should be 5.
Previous problems:
I messed up the distance calculation.
I placed the circle's from 0...499 which should be 0...500
I didn't use float, which decreased the 'resolution'
Disclamer
It might just be that I've reached a limit but this demonstration used 1 million points and got 3.16. considering I've got about 900 billion I think it could be more precisely.
I do understand that if I want to calculate π this isn't the right way to go about it, but I just want to make sure that everything is right so I was hoping anyone could spot something wrong or do I just need more 'dots'.
EDIT: There are quite a few mentions about how unrealistic the numbers where, these mentions where correct and I have now updated them to be correct.
You could easily estimate what kind of error (error bars) you should get, that's the beauty of the Monte Carlo. For this, you have to compute second momentum and estimate variance and std.deviation. Good thing is that collected value would be the same as what you collect for mean, because you just added up 1 after 1 after 1.
Then you could get estimation of the simulation sigma, and error bars for desired value. Sorry, I don't know enough Javascript, so code here is in C#:
using System;
namespace Pi
{
class Program
{
static void Main(string[] args)
{
ulong N = 1_000_000_000UL; // number of samples
var rng = new Random(312345); // RNG
ulong v = 0UL; // collecting mean values here
ulong v2 = 0UL; // collecting squares, should be the same as mean
for (ulong k = 0; k != N; ++k) {
double x = rng.NextDouble();
double y = rng.NextDouble();
var r = (x * x + y * y < 1.0) ? 1UL : 0UL;
v += r;
v2 += r * r;
}
var mean = (double)v / (double)N;
var varc = ((double)v2 / (double)N - mean * mean ) * ((double)N/(N-1UL)); // variance
var stdd = Math.Sqrt(varc); // std.dev, should be sqrt(Pi/4 (1-Pi/4))
var errr = stdd / Math.Sqrt(N);
Console.WriteLine($"Mean = {mean}, StdDev = {stdd}, Err = {errr}");
mean *= 4.0;
errr *= 4.0;
Console.WriteLine($"PI (1 sigma) = {mean - 1.0 * errr}...{mean + 1.0 * errr}");
Console.WriteLine($"PI (2 sigma) = {mean - 2.0 * errr}...{mean + 2.0 * errr}");
Console.WriteLine($"PI (3 sigma) = {mean - 3.0 * errr}...{mean + 3.0 * errr}");
}
}
}
After 109 samples I've got
Mean = 0.785405665, StdDev = 0.410540627166729, Err = 1.29824345388086E-05
PI (1 sigma) = 3.14157073026184...3.14167458973816
PI (2 sigma) = 3.14151880052369...3.14172651947631
PI (3 sigma) = 3.14146687078553...3.14177844921447
which looks about right. It is easy to see that in ideal case variance would be equal to (Pi/4)*(1-Pi/4). It is really not necessary to compute v2, just set it to v after simulation.
I, frankly, don't know why you're getting not what's expected. Precision loss in summation might be the answer, or what I suspect, you simulation is not producing independent samples due to seeding and overlapping sequences (so actual N is a lot lower than 900 trillion).
But using this method you control error and check how computation is going.
UPDATE
I've plugged in your numbers to show that you're clearly underestimating the value. Code
N = 893_547_800_000UL;
v = 701_766_448_388UL;
v2 = v;
var mean = (double)v / (double)N;
var varc = ((double)v2 / (double)N - mean * mean ) * ((double)N/(N-1UL));
var stdd = Math.Sqrt(varc); // should be sqrt(Pi/4 (1-Pi/4))
var errr = stdd / Math.Sqrt(N);
Console.WriteLine($"Mean = {mean}, StdDev = {stdd}, Err = {errr}");
mean *= 4.0;
errr *= 4.0;
Console.WriteLine($"PI (1 sigma) = {mean - 1.0 * errr}...{mean + 1.0 * errr}");
Console.WriteLine($"PI (2 sigma) = {mean - 2.0 * errr}...{mean + 2.0 * errr}");
Console.WriteLine($"PI (3 sigma) = {mean - 3.0 * errr}...{mean + 3.0 * errr}");
And output
Mean = 0.785370909522692, StdDev = 0.410564786603016, Err = 4.34332975349809E-07
PI (1 sigma) = 3.14148190075886...3.14148537542267
PI (2 sigma) = 3.14148016342696...3.14148711275457
PI (3 sigma) = 3.14147842609506...3.14148885008647
So, clearly you have problem somewhere (code? accuracy lost in representation? accuracy lost in summation? repeated/non-independent sampling?)
any FPU operation will decrease your accuracy. Why not do something like this:
let inside = 0;
for (let i = 0; i < iterations; i++)
{
var X = Math.random();
var Y = Math.random();
if ( X*X + Y*Y <= 1.0 ) inside+=4;
}
if we probe first quadrant of unit circle we do not need to change the dynamic range by size and also we can test the distances in powered by 2 form which get rid of the sqrt. These changes should increase the precision and also the speed.
Not a JAVASCRIPT coder so I do not know what datatypes you use but you need to be sure you do not cross its precision. In such case you need to add more counter variables to ease up the load on it. For more info see: [edit1] integration precision.
As your numbers are rather big I bet you crossed the boundary already (there should be no fraction part and trailing zeros are also suspicious) For example 32bit float can store only integers up to
2^23 = 8388608
and your 698,565,481,000,000 is way above that so even a ++ operation on such variable will cause precision loss and when the exponent is too big it even stop adding...
On integers is this not a problem but once you cross the boundary depending on internal format the value wraps around zero or negates ... But I doubd that is the case as then the result would be way off from PI.
I have this code
if ($('input#grommet').is(':checked')) {
if (width <= 96) {
var grommetQTY = 4;
} else if (width > 96) {
grommetQTY = (Math.floor(width / 24));
grommetQTY = grommetQTY - 4;
grommetQTY = grommetQTY * 2;
grommetQTY = grommetQTY +4;
}
}
and I need to add 2 to the grommetQTY for each whole 24 inches (2 feet) over 96 width. Is there a way to do this?
What this is attempting to accomplish is giving the pricing for a banner. We add 2 more grommets at 2 feet intervals, but because this is custom sizing, it could be 96 feet wide, and I don't want to have to write an else if statement for each two foot interval. I am hoping there is a way to only add two to the quantity everytime the width goes another 24 inches over the standard 96 inch width so if width is 96 or less, qty is 4, at 120 its 6, at 144 its 8, etc
Rather than coming up with the equation for this, here is a for loop that will do what you need:
var grommetQTY = 0;
for(var i = 96; i < n; i++)
if(i%24 == 0)
grommetQTY += 2;
where n is the length. This is terrible inefficient and could be sped up by just doing:
var grommetQTY = 0;
for(var i = 96; i < n; i+=24)
grommetQTY += 2;
This is nicer but still not ideal. The ideal solution in your case would be an equation.
P.S - The equation is Math.floor( Math.max((n - 96), 0) / 24 ) * 2 + 4 if I understand you correctly.
You could do something like this:
var extra = width - 96
var grommetQTY = 4;
if (extra > 0) {
grommet += Math.floor((extra / 24)) * 2;
}
The variable extra holds, as the name implies, extra length that you would want to take into consideration. If it's 0 or below that means it's 96 and under.
Then, for extra > 0 you could alternatively change it to extra >= 24 as any extra value less than 24 will return 0.
Math.pow(2, grommetQTY) * (Math.floor(96 / 24))
2 to the grommetQTY for each whole 24 inches in 96. Is that what you need?
Math.pow(a, b) gives a to the power of b
Edit:
var qty = (Math.floor(n / 24)) * 2
Where n is the pixels (96 in your example).
Edit:
var qty = 4 + ((width > 96) ? ((Math.floor((width - 96) / 24) * 2) : 0);
Is that it?
Javascript>
If you are in the data science industry, you would be bothered if you don't have normal distribution table. I came across the article in Stackoverflow that converts z-score to probability in JavaScript. What I really want to know is the reverse calculation of this function.
/**
* #param {number} z - Number of standard deviations from the mean.
*/
function GetZPercent(z) {
// If z is greater than 6.5 standard deviations from the mean
// the number of significant digits will be outside of a reasonable
// range.
if (z < -6.5)
return 0.0;
if (z > 6.5)
return 1.0;
var factK = 1;
var sum = 0;
var term = 1;
var k = 0;
var loopStop = Math.exp(-23);
while (Math.abs(term) > loopStop) {
term = 0.3989422804 * Math.pow(-1, k) * Math.pow(z, k) / (2 * k + 1) /
Math.pow(2, k) * Math.pow(z, k + 1) / factK;
sum += term;
k++;
factK *= k;
}
sum += 0.5;
return sum;
}
I have a sense of how to convert z-score into the probability. But, I have no idea how to calculate the z-score(Standard deviation) from corresponding probability in javascript. For example, If I put in 0.95 (or 95%), I can expect to get 2.25 standard deviation. Above code gives me 95%, if I enter 2.25.
I found that this code also works. Use critz(p) to convert probability to z-score. For example we can expect 1.65 from critz(0.95) as 95% corresponds to 1.65 standard deviation in z-score.
/* The following JavaScript functions for calculating normal and
chi-square probabilities and critical values were adapted by
John Walker from C implementations
written by Gary Perlman of Wang Institute, Tyngsboro, MA
01879. Both the original C code and this JavaScript edition
are in the public domain. */
/* POZ -- probability of normal z value
Adapted from a polynomial approximation in:
Ibbetson D, Algorithm 209
Collected Algorithms of the CACM 1963 p. 616
Note:
This routine has six digit accuracy, so it is only useful for absolute
z values <= 6. For z values > to 6.0, poz() returns 0.0.
*/
var Z_MAX = 6;
function poz(z) {
var y, x, w;
if (z == 0.0) {
x = 0.0;
} else {
y = 0.5 * Math.abs(z);
if (y > (Z_MAX * 0.5)) {
x = 1.0;
} else if (y < 1.0) {
w = y * y;
x = ((((((((0.000124818987 * w
- 0.001075204047) * w + 0.005198775019) * w
- 0.019198292004) * w + 0.059054035642) * w
- 0.151968751364) * w + 0.319152932694) * w
- 0.531923007300) * w + 0.797884560593) * y * 2.0;
} else {
y -= 2.0;
x = (((((((((((((-0.000045255659 * y
+ 0.000152529290) * y - 0.000019538132) * y
- 0.000676904986) * y + 0.001390604284) * y
- 0.000794620820) * y - 0.002034254874) * y
+ 0.006549791214) * y - 0.010557625006) * y
+ 0.011630447319) * y - 0.009279453341) * y
+ 0.005353579108) * y - 0.002141268741) * y
+ 0.000535310849) * y + 0.999936657524;
}
}
return z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5);
}
/* CRITZ -- Compute critical normal z value to
produce given p. We just do a bisection
search for a value within CHI_EPSILON,
relying on the monotonicity of pochisq(). */
function critz(p) {
var Z_EPSILON = 0.000001; /* Accuracy of z approximation */
var minz = -Z_MAX;
var maxz = Z_MAX;
var zval = 0.0;
var pval;
if( p < 0.0 ) p = 0.0;
if( p > 1.0 ) p = 1.0;
while ((maxz - minz) > Z_EPSILON) {
pval = poz(zval);
if (pval > p) {
maxz = zval;
} else {
minz = zval;
}
zval = (maxz + minz) * 0.5;
}
return(zval);
}
Here is a function that does an opposite calculation (probability to z-score). This snippet allows you to input the probability and the the corresponding z-score is displayed:
function percentile_z(p) {
if (p < 0.5) return -percentile_z(1-p);
if (p > 0.92) {
if (p == 1) return Infinity;
let r = Math.sqrt(-Math.log(1-p));
return (((2.3212128*r+4.8501413)*r-2.2979648)*r-2.7871893)/
((1.6370678*r+3.5438892)*r+1);
}
p -= 0.5;
let r = p*p;
return p*(((-25.4410605*r+41.3911977)*r-18.6150006)*r+2.5066282)/
((((3.1308291*r-21.0622410)*r+23.0833674)*r-8.4735109)*r+1);
}
// I/O handling
function calc() {
var p = +document.getElementById("prob").value;
var z = percentile_z(p);
document.getElementById("z").textContent = z.toFixed(4);
}
calc();
input { width: 5em }
Probability (between 0 and 1):
<input type="number" id="prob" step="0.0001" min="0" max="1" value="0.9500" oninput="calc()"><p>
Z Score: <span id="z"></span>
For a probability of 0.95 it returns a z-score of 1.6449. See also this table as reference.
Derived from easycalculation.com
So, I have a code that is rolling a random number from 1024 to 4096 and changing backgroundPosition to rolled number. (jsfiddle)
function slide()
{
var x = 1;
var y = 30;
var z = Math.floor((Math.random() * 4096) + 1024); // background offset
var zz = Math.floor((Math.random() * 14) + 0); // number
var clr = setInterval(function()
{
if(x >= z) x = 1;
document.getElementById("slide").style.backgroundPosition = x+"px 0px";
x+=y;
y-=0.1;
if (y<=0)
{
clearInterval(clr);
document.getElementById('rolledNumber').innerHTML = z;
}
}
,10);
}
"z" is a random number between 1024 and 4096, how can I check what number on image it is? I tried if (z >= 2285 && z <= 2210){var zz = 4;}, where "zz" is a number on image, but it's not working.
Hope you guys can understand it.
You have a few problems here:
1) if (z >= 2285 && z <= 2210)
is impossible. There is no number that satisfies both "larger than 2284" AND "smaller than 2211".
2) "z" is a random number between 1024 and 4096
var z = Math.floor((Math.random() * 4096) + 1024); will actually create a random number between 1024 and 5120. Imagine the case where Math.random() returns 1. Your result would be 1 * 4096 + 1024, or 5120.
3) Your background image is repeating - if you stick to one set of 15 numbers, you could access the number by mapping the pixel offset to an array.. something like this:
var boxWidth = 150;
var boxes = [1, 14, 2, 13, 3, 12, 4, 0, 11, 5, 10, 6, 9, 7, 8];
function getNumber (offset) {
var boxNumber = Math.floor(offset / boxWidth);
return boxes[boxNumber];
}
4) No one knows the application of this logic other than you, please reword your question such that it actually makes any sense and act like you've tried to find the problem yourself.
If anyone is interested - I figured out how to do this. I'm checking "x" value, and if it's between x and y, that means rolled number is z. Fragment of code:
if (x >= 410 && x <= 485){var rolledNumber = 1;}
if (x >= 335 && x <= 410){var rolledNumber = 14;}
if (x >= 260 && x <= 335){var rolledNumber = 2;}
I am visualising bubbles for cities, bigger if the city has a bigger value. Eg:
London: 14500
New York: 100
Tokyo: 1100
The values range from ~100-15000
I am having trouble creating a function that will return reasonable values, so that the 100 value bubbles aren't too small. The only way I could think to do this is to set a minimum size, eg:
if (size < 5) { size = 5 }
However, this causes the cities with values of ~100 to look very similar to cities with values of ~1000. I'd like the values of approx 0-15000 to return as values between 0.5 and 1 (or something similar). How would this be done?
Here's what I have so far, but like I said it's causing values of 100 and values of 1000 to both be under the min value:
var minBulletSize = 7.5;
var maxBulletSize = 20;
var maxSquare = maxBulletSize * maxBulletSize * 2 * Math.PI;
var minSquare = minBulletSize * minBulletSize * 2 * Math.PI;
// create circle for each location
for (var i = 0; i < mapData.length; i++) {
var dataItem = mapData[i];
var value = dataItem.value;
// calculate size of a bubble
var square = (value/1000 - minBulletSize) / (maxBulletSize - minBulletSize) * (maxSquare - minSquare) + minSquare;
if (square < minSquare) {
square = minSquare;
}
if (square > maxSquare) {
square = maxSquare;
}
var size = Math.sqrt(square / (Math.PI * 2));
var id = dataItem.code;
}
I have taken a look at how to make a logarithmic function to look "logarithmic" within the constraints of 0.5 and 1 :
Math.log10(x / 0.8 + 1) / 3 + 0.5 where x is in between 0 to 24.5.
This is purely a function that seems to look good for me where you can get very dynamic numbers early although a clear growth can be seen in larger numbers.
Feel free to mess around with the numbers, this is VERY subjective.
Next you will need to fit in your 100~15000 range within 0 to 24.5.
I would simply do a x = (x - 100) / 608.16 to get your range to be within 0 to 24.5.
var minBulletSize = 7.5;
var maxBulletSize = 20;
var maxSquare = maxBulletSize * maxBulletSize * 2 * Math.PI;
var minSquare = minBulletSize * minBulletSize * 2 * Math.PI;
// create circle for each location
for (var i = 0; i < mapData.length; i++) {
var dataItem = mapData[i];
var value = dataItem.value;
// assuming value is in between 100 and 15000
value = (value - 100) / 608.16;
value = Math.log10(value / 0.8 + 1) / 3.0 + 0.5;
// value will be in between 0.5 and 1 on a logarithmic scale.
// Do what you want with it :)
}
Tinker the values within the functions until you find a perfect curve for you.