How to generate pseudo random numbers and row-counts in Tableau? I didn't find any built-in functions (like 'RAND', 'RCOUNT').
Edit:
Just learned that there is a Random() function in Tableau. It is not in the library but if you use it anyway, it will tell you that the formula is valid and create a value between 0 and 1.
Original and still valid answer in case you want to use officially supported functions:
Since Tableau is used to create graphs based on your data, there is usually little use for random numbers (would you explain what you need them for?)
However you could use an approach like this to work around this limitation: http://community.tableau.com/docs/DOC-1474
Basically getting a semi-random seed out of the time, combine it with other values based on table calculations and multiplying it with other semi-random values
Seed
(DATEPART('second', NOW()) + 1) * (DATEPART('minute', NOW()) + 1) * (DATEPART('hour', NOW()) + 1) * (DATEPART('day', NOW()) + 1)
Random Number
((PREVIOUS_VALUE(MIN([Seed])) * 1140671485 + 12820163) % (2^24))
Random Int
INT([Random Number] / (2^24) * [Random Upper Limit]) + 1
Where [Random Upper Limit] is a user defined value to limit the range of the result.
Related
I think I've hit the upper limit level for random generating numbers.
Is there any workaround for this?
I need to generate ten unique, 19-digit, random numbers in one formula/string.
I have this: =TRUNC (RAND() * (9999999999999999999 - 1) + 1) but spreadsheet rewrites it to:
=TRUNC (RAND() * (9999999999999990000 - 1) + 1)
so I guess the limit is 9999999999999990000.
Desired output format in A1:
2459759093970314589,6393667943286134368,4897561254458152397, etc.
Numeric precision in Excel is ~15 significant digits. An alternative would be to generate the random numbers as strings (the fist character needs to be in the range of 1 to 9, the others from the range of 0-9). Something like this:
=CONCAT(
TRUNC(RAND()*9+1);
TRUNC(RAND()*10);
TRUNC(RAND()*10);
TRUNC(RAND()*10);
...
)
google-spreadsheets
=TRANSPOSE(regexextract(JOIN("",ArrayFormula(RANDBETWEEN(row(INDIRECT("a1:a"&A1*A2))^0-1,9))),rept("(\d{"&A1&"})",A2)))
Situation
After working on a coding kata I finally got the algorithm to work on my small test cases.
Only to find out it did not work on a large scale, the time is not an issue but the size of the numbers are.
In one of my calculations in one of the test cases I need to perform the following calculation.
var numberOfColumns = 34359738368;
var numberOfRows = 28827050410;
var valueOverflow = 13719506;
var totalOfSingleRow = (numberOfColumns * (numberOfColumns - 1))/2;
var totalGridValue = totalOfSingleRow * numberOfRows;
var result = (totalOfSingleRow * totalGridValue) % valueOverflow;
Because the top row is sequential, I can calculate the sum of the first row by doing (numberOfColumns * (numberOfColumns - 1))/2;.
Then I need to multiply that answer by the number of rows and apply the modulo to get my resulting value.
The problem
The problem is that Javascript can only calculate reliable with number less than 9007199254740991.
Only the calculation above results in a totalGridValue of 17016487081526963049249353236480.
You can imagine that my calculation does not result in the desired value of 10552574 because the value gets truncated to 1.7016487081526963e+31.
This results in the wrong value of 8479672
Question
How can I alter my calculation so the result becomes the desired 10552574.
I've tried applying the modulo operator sooner on the numberOfColumns without the desired result.
I've also looked at adding two large values as string but this process would become to slow as I have to add two strings to many times.
Note
Because I need to submit this on codewars, I cannot use any external libraries!
I can use other languages though, but I know it is possible in javascript.
I think you were on the right track with moving the modulus operation further up the chain, but I wouldn't use the modulo operator for that. Instead, use regular floating point division, and carry that value through to the last step, when all other calculations are done, then convert that float's decimal part into an integer. Basically, with pure division, you're just doing a transformation on the value, rather than changing the value. Once you go to the modulus, you've changed the value. (I'd also change the totalSingleRow formula to divide the big values then multiply the results, rather than multiply then divide.)
I agree that moving the modulus operation further up the chain is the correct basic idea. The one subtlety is handling the calculation of totalOfSingleRow, because it involves a division by two. I think what you need to do is perform that stage modulo (2 * valueOverflow), and only compute the result modulo valueOverflow at the end. Perhaps as follows:
var doubleOverflow = 2 * valueOverflow;
var totalOfSingleRow = (((numberOfColumns % doubleOverflow) * (numberOfColumns + doubleOverflow - 1)) / 2) % valueOverflow;
var totalGridValue = (totalOfSingleRow * (numberOfRows % valueOverflow)) % valueOverflow;
var result = (totalOfSingleRow * totalGridValue) % valueOverflow;
You'll need to check that (4 * valueOverflow*valueOverflow) is less than the maximum integer value that can be represented correctly.
In excel below formula will generate random number from a normal distribution with mean 10 and variance 1. Is there a way to set a fix seed so that i get a fix set of random numbers all the time? I am using Excel 2010
=NORMINV(RAND(),10,1)
You can implement your own random number generator using spreadsheet functions. For example, C++11 has a Lehmer random number generator called minstd_rand which is obtained by the recurrence
X = X*g (mod m)
where g = 48271 and m = 2^31-1
In A1 you can place your seed value. In A2 enter the formula:
=MOD(48271*A1,2^31-1)
and copy it down however far you need.
In B2 enter =A2/(2^31-1) and in C2 enter =NORM.INV(B2,10,1), copying as needed. Note that you can always replace the seed value in A1 by
=RANDBETWEEN(1,2^31-2)
if you want to turn volatile randomness back on.
The following screenshot shows 25 random normal variables generated in this fashion:
As you can tell from the histogram the distribution seems roughly normal.
You could use a VBA UDF() based on the Rnd() function. See:
Repeating random variables in VBA
I am not pretending that it is a perfect solution, but that works for me.
The beauty of it, is that I can assign a random number to a particular cell:
Public Function GetRandom(seed As Double, min As Double, max As Double) As Double
Dim colrow As Double
Dim range As Double
range = max - min
If (Application.Caller.Column() = Application.Caller.Row()) Then
colrow = (Log(Application.Caller.Column() + 1) * Log(Application.Caller.Row() + 1)) * seed
Else
colrow = (Log(Application.Caller.Column() + 1) / Log(Application.Caller.Row() + 1)) * seed
End If
Rnd (-1)
Randomize colrow
test = Rnd * range - range / 2
GetRandom = colrow
End Function
Usage:
=GetRandom($Z$1,1,-1)
I my example, the seed value is in Z1 cell, but of course in can be in any other cell. It also allow me to setup min and max values.
A pragmatic solution is to copy values from your sample into a new range.
I'm creating a website in which 2 items out of a possible 117 are chosen and compared in different ways. I need a way to assign each of these matchups a unique number so they can be easily stored in a database and what not. I've seen pairing functions, but I cannot find one in which order doesn't matter. For example, I want the unique number for 2 and 17 to be the same as 17 and 2. Is there an equation that will satisfy this?
It depends on what programming language you are using.
In Java for example it would be quite easy, because same seed is producing the same random number sequence. So you could simple use the sum of both random numbers
Long seed = 2L + 17L;
Long seed2 = 17L+2L;
Random random = new Random(seed);
Random random2 = new Random(seed2);
Boolean b = (random.nextLong() == random2.nextLong()) //true
However, this would also return the same value for 1+18, 0+19 and so on - whatever sums up to 19.
So, to get really unique numbers "per pair" you would need to shift one of them. IE, with 117 entries, you could multiply the SMALLER (or larger) by 1000:
Long seed = 2L * 1000 + 17L;
....
Then you have a unique random number for 2,17 and 17,2 - but 19,0 or 0,19 would produce a DIFFERENT random number.
ps.: if it should ALWAYS return the same for 2,19 - the result is not really a random number, isn't it?
I know that the question dates from 2014, but I still wanted to add the following answer.
You could use the product of prime numbers to do this. For example, if your pair is (2,4), then you could use the product of the 2nd prime number (=3) and the 4th prime number (=7) as your id (= 3*7 = 21).
In order to do this though with your 117 possible combinations, you would need to pre-calculate all first 117 prime numbers and store them for example in an array or a hash table and then do something like (in JavaScript):
var primes = [2,3,5,7,...];
var a = 2;
var b = 17;
var id = primes[a-1]*primes[b-1];
Note that if you want to decode them as well, things are going to be more difficult since you would need to calculate the prime factorization of your id.
In my app I need to run a 5 digits number through an algorithm and return a number between the given interval, ie:
The function encode, gets 3 parameters, 5 digits initial number, interval lower limit and interval superior limit, for example:
int res=encode(12879,10,100) returns 83.
The function starts from 12879 and does something with the numbers and returns a number between 10 and 100. This mustn't be random, every time I pass the number 12879 to the encode function must always return the same number.
Any ideas?
Thanks,
Direz
One possible approach:
compute the range of your interval R = (100 - 10) + 1
compute a hash modulo R of the input H = hash(12879) % R
add the lower bound to the modular hash V = 10 + H
Here the thing though - you haven't defined any constraints or requirements on the "algorithm" that produces the result. If all you want is to map a value into a given range (without any knowledge of the distribution of the input, or how input values may cluster, etc), you could just as easily just take the range modulo of the input without hashing (as Foo Bah demonstrates).
If there are certain constraints, requirements, or distributions of the input or output of your encode method, then the approach may need to be quite different. However, you are the only one who knows what additional requirements you have.
You can do something simple like
encode(x,y,z) --> y + (x mod (z-y))
You don't have an upper limit for this function?
Assume it is 99999 because it is 5 digits. For your case, the simplest way is:
int encode (double N,double H,double L)
{
return (int)(((H - L) / (99999 - 10000)) * (N - 10000) + 10);
}