Random block without using random blocks!

Yes! As you saw in the title, this is a block that can generate random numbers without using block. It generates a list with raw random numbers that can be processed to make anything random. Here are some examples:

untitled script pic - 2022-03-25T222538.924
untitled script pic - 2022-03-25T222548.469
As you can see, it doesn't generate the same number...

untitled script pic - 2022-03-25T222712.643
You can generate more than one number!

Numbers will not be repeated.


Copy and Import:

<blocks app="Snap! 7, https://snap.berkeley.edu" version="2"><block-definition s="new random with length %&apos;length&apos;" type="reporter" category="operators"><comment w="184" collapsed="false">Creates a list with raw random numbers.</comment><variables><list struct="atomic" id="3">data</list></variables><header></header><code></code><translations></translations><inputs><input type="%n">5</input></inputs><script><block s="doIf"><block s="reportNot"><block s="reportIsA"><block var="data"/><l><option>list</option></l></block></block><script><block s="doSetVar"><l>data</l><block s="reportAtomicMap"><block s="reifyReporter"><autolambda><block s="reportModulus"><block s="reportPower"><block s="reportQuotient"><block var="value"/><block var="index"/></block><l>10</l></block><block s="reportDate"><l><option>time in milliseconds</option></l></block></block></autolambda><list><l>value</l><l>index</l></list></block><block s="reportAtomicMap"><block s="reifyReporter"><autolambda><block s="reportDifference"><block s="reportVariadicProduct"><list><block s="reportVariadicSum"><list><block s="reportVariadicProduct"><list><block s="reportVariadicSum"><list><block s="reportVariadicProduct"><list><block s="reportVariadicSum"><list><block s="reportVariadicProduct"><list><block s="reportVariadicSum"><list><block s="reportVariadicProduct"><list><block s="reportVariadicSum"><list><block s="reportVariadicProduct"><list><block s="reportDate"><l><option>year</option></l></block><l>365</l></list></block><block s="reportDate"><l><option>month</option></l></block></list></block><l>30</l></list></block><block s="reportDate"><l><option>date</option></l></block></list></block><l>24</l></list></block><block s="reportDate"><l><option>hour</option></l></block></list></block><l>60</l></list></block><block s="reportDate"><l><option>minute</option></l></block></list></block><l>60</l></list></block><block s="reportDate"><l><option>second</option></l></block></list></block><l>1000</l></list></block><block s="reportDate"><l><option>time in milliseconds</option></l></block></block></autolambda><list></list></block><block s="reportNumbers"><l>1</l><l>1000</l></block></block></block></block></script><comment w="87" collapsed="false">This is the list that store candidates.</comment></block><block s="doDeclareVariables"><list><l>result</l></list></block><block s="doSetVar"><l>result</l><block s="reportNewList"><list></list></block></block><block s="doWarp"><script><block s="doRepeat"><block var="length"/><script><block s="doAddToList"><block s="reportListItem"><block s="reportVariadicSum"><list><block s="reportVariadicProduct"><list><block s="reportDifference"><block s="reportQuotient"><block s="reportDate"><l><option>time in milliseconds</option></l></block><l>1000</l></block><block s="reportMonadic"><l><option>floor</option></l><block s="reportQuotient"><block s="reportDate"><l><option>time in milliseconds</option></l></block><l>1000</l></block></block></block><l>1000</l></list></block><l>1</l></list></block><block var="data"/></block><block var="result"/><comment w="106" collapsed="false">Select a candidate and collects that number.</comment></block><block s="doSetVar"><l>data</l><block s="reportModulus"><block s="reportPower"><block s="reportVariadicSum"><list><block var="data"/><block s="reportListItem"><l><option>last</option></l><block var="result"/></block></list></block><l>10</l></block><block s="reportDate"><l><option>time in milliseconds</option></l></block></block><comment w="115" collapsed="false">Replace non-selected candidates to new ones.</comment></block></script></block></script></block><block s="doReport"><block var="result"/></block></script></block-definition></blocks>

(C) 2022 ScratchModification

project link?

Whoops! I will add it

Interesting. My guess is that it's more complicated than necessary, because the current year, month, ... second are all functions of the current time in milliseconds, and it looks as if you think they're independent. For the same reason, the results might not be uniformly distributed, but that's beyond my math abilities to determine.

Yes! That's right, but I have a question.

  • Does this block generate actually random numbers?

I've created a block similar to the primitive one:

It gave me these numbers:

With the primitive one:

Which is better to use? (without considering performance)

No, it generates pseudo random numbers. True random can only be determined in the real world, for example, using a lava lamp.

Oh well, this uses imperfections to make the numbers:

  • Current time in milliseconds with processes, which determines a random delay.
  • Floating-point arithmetic, using large numbers and then using operators with them will cause a loss of precision, which makes the number more random

And yeah, I did have to make a more accurate question:

  • Is this a good pseudo-random generator?

Are you sure?

Yes. Look at the code:

It makes the number big, when Snap! starts to use Floating-point Arithmetic.

But are you sure floating-point arithmetic is random? I don't think it is. It just loses precision, which I think actually makes it less random.

I mean, it uses modulo function, which returns the remainder when you divide that big number with the Unix time. And when it loses precision, that could make differences which (for me) it's essential to make something random.

No. That would be right if the loss of precision were chaotic, maybe, but it's not; floating point numbers are all rational, and the probability of a randomly chosen real number being rational is zero.

Choosing a value at random from a finite set (such as the integers between A and B) is mathematically easy to get right. You run your algorithm a million times (or some number much much larger than |B−A|) and you should get each number with very nearly equal frequency.

But choosing a random integer with no limits on size is much harder to analyze mathematically, and choosing a random real number is even harder.

In principle, since there are only finitely many floating point values (for a given width), all you have to do is run your algorithm 2^1024 times, or some such thing, to check its quality as a pseudorandom number generator. But there are enough floats so that there won't be any more human beings to care when that check finishes, so we have to do the math as if any real value were possible in floating point, or as if any integer value, regardless of magnitude, fit in a computer. (Even bignums have a limit, since there's only a finite amount of computer memory possible in the universe.)

Since we can't really count how many times each value occurs, they use other tests to evaluate randomness. For example, they can check normality: When you represent the chosen numbers in base ten, does every digit occur equally often, does every string of two digits occur equally often... does every string of n digits occur equally often for all n? (Note that no rational number is normal, a result that I found deeply funny in high school.)

For integers, you can ask, "Are 50% of these numbers 0 mod 2" and similarly for other moduli.

But, tl;dr, it takes some very sophisticated probability theory to be confident in a pseudorandom number generator. So in practice you just have faith in the applied mathematicians who worked on your computer's math library.

How would I determine that this algorithm is useful?

If anyone wants to test this algorithm in other programming languages, here is the source code:


def random(length):
  from datetime import datetime
  from time import time
  data = [int(((((((((((datetime.now().year * 365) + datetime.now().month) * 30) + datetime.now().day) * 24) + datetime.now().hour) * 60) + datetime.now().minute) * 60) + datetime.now().second) * 1000 - time() * 1000) for _ in range(1, 1001)]
  index = 0
  for value in data:
    data[index] = int(((value / (index + 1)) ** 10) % (time() * 1000))
    index += 1
  result = []
  index = 0
  for _ in range(1, length + 1):
    item = int((time() - int(time())) * 1000)
    result += [data[item]]
    data = [int((value + result[index]) % (time() * 1000)) for value in data]
    index += 1
  return result

I am so much not an expert at this, sorry. Look up pseudorandom numbers in Knuth, or in Wikipedia, or something.

Nitpicking a bit, but true randomness is actually kind of fundamentally impossible in reality which is why it doesn't work in computing- If you knew every variable about the real world you could predict literally everything.

True randomness exists without tangible variables that could ever be acquired, I guess, it's impossible to acquire and impossible to predict.

Pseudo-randomness is the best anyone will get.

quantum machanics: You sure?

Have you thought of the brain though? :)

Unless the brain turns out to be a quantum device, which is quite possible, its capabilities are the same as those of (classical) computers. In particular, it's no more capable of true randomness.

Exactly. It doesn't have to be very complicated; as I keep saying, a simple diode is a quantum device; when you put it in a circuit, the voltage drop across it is ≈0.7 volts, but the exact value is different every time you measure it.