Herhangi bir rastgele tamsayı üret


17

Programınız / işleviniz

  • tam olarak bir tamsayı çıktılar
  • pozitif olasılıkla herhangi bir tamsayıyı çıktılar
  • en az% 50 olasılıkla 1.000.000'dan büyük veya -1.000.000'den küçük bir tamsayı çıktılar.

Örnek çıktılar (hepsi mümkün olmalıdır):

59875669123
12
-42
-4640055890
0
2014
12
24
-7190464664658648640055894646646586486400558904644646646586486400558904646649001

Açıklamalar:

  • Sondaki satır kesmesine izin verilir.
  • Baştaki sıfırlara izin verilmez.
  • -0 izin verilir.

En kısa kod kazanır.


2
@Optimizer neden tekdüze olasılık varsayıyorsunuz? Soru bunu söylemiyor. Aslında o noktadan itibaren, dağılımın en az% 50'si [-1 milyon, 1 milyon] dışında kaldığı sürece tekdüze olması gerekmediği açıktır .
hobbs

10
" Tüm tamsayılar arasında eşit dağılım " üreten bir çözüm mümkün değildir. Sonsuz sayıda tamsayı vardır, bu yüzden her bir tamsayı 0 olasılığı ile görünecektir. (Veya: Sonlu bir sayı çıkarmak, sonsuz sayıda başkalarını ihmal ettiğiniz anlamına gelir!) Herhangi bir çözüm, P'ye ulaşmak için daha yüksek değerleri reddetmek zorunda kalacaktır. ) 1 =.
joeytwiddle

2
@Ypnypn Bilgisayarın RAM'i de bir sınır değil. Kısmi çıktınızı hiçbir yerde saklamanız gerekmez.
jimmy23013

4
@GiantTree - way too long to fit in an integer- Bunu varsayarsak bu not geçerlidir integeraracı intmutlaka geçerli bir varsayım olmayan bir 32/64 bit kemer, üzerinde veri türü. "Tamsayı" , boyut sınırlaması olmayan bir matematik terimi olarak başladı .
Sahte İsim

5
Çıktıya ilişkin kararlarını vermek için sözde rasgele sayı üreteci kullanan herkes neredeyse tüm tam sayıları hariç tutar ve üretilebilecek tam sayıların boyutuna bir üst sınır koyar (PRNG'nin sınırlı bir süre olduğu varsayılarak). Bu, cevaplarda göz ardı edilebilir mi veya geçerli bir cevap gerçek bir rasgele sayı üreteci gerektiriyor mu?
trichoplax

Yanıtlar:


12

CJam, 16 14 13 bayt

0{Kmr(+esmr}g

Bu çok uzun bir süre çalışacaktır , çünkü döngünün sona ermesi gerekip gerekmediğini belirlemek için geçerli zaman damgasını (10 12 sırasına göre ) kullanır. Bunu en kısa olduğu gibi gönderme olarak kullanıyorum, ancak kendi değerlerine sahip iki 14 bayt alternatifi var:

0{esmr(+esmr}g

Bu , PRNG dönemi ile sınırlı değildir , çünkü tüm rastgele sayıların geçerli zaman damgasına bağlıdır. Bu nedenle, negatif veya hatta küçük pozitif sayıların kaybolma olasılığı az olsa da, bu herhangi bir sayı üretebilmelidir.

Aşağıda, 3e5zaman damgası yerine kullanılan eşdeğer bir sürüm bulunmaktadır . Ve 20ilk aralık için (13 baytlık gönderim olarak). Çok daha hızlı ve aynı zamanda tüm kurallara uyuyor. Makul bir çalışma süresi ve küçük kod boyutu tutarken 1.000.000'un üzerindeki sayılar için% 50 olasılık elde etmek bir tür sınırlayıcı durumdur. Açıklama ve matematiksel gerekçe bu sürüme aittir:

0{Kmr(+3e5mr}g

Bu genellikle birkaç saniye sürer. Değiştirebilirsiniz52 hızlı çalışmasını sağlamak için tuşunu a ile . Ancak daha sonra% 50 olasılık gereksinimi 1.000.000 yerine yalnızca 1.000 için karşılanacaktır.

Ben 0'dan başlıyorum. O zaman 1 / (3 * 10 5 ) olasılığı ile ayrıldığım bir döngü var . Bu döngü içinde, koşu toplamıma -1 ile 18 (dahil) arasında rastgele bir tamsayı ekliyorum. Her tamsayının çıkacağı sonlu (küçük de olsa) bir olasılık vardır, pozitif tamsayılar negatif olanlardan çok daha olasıdır (Yaşamınızda negatif bir tane göreceğinizi düşünmüyorum). Böylesine küçük bir olasılıkla ayrılmak ve çoğu zaman arttırmak (ve çıkarma işleminden çok daha fazlasını eklemek) genellikle 1.000.000'u aşmamızı sağlar.

0              "Push a 0.";
 {          }g "Do while...";
  Kmr          "Get a random integer in 0..19.";
     (         "Decrement to give -1..18.";
      +        "Add.";
       3e5mr   "Get a random integer in 0..299,999. Aborts if this is 0.";

Bazı matematiksel gerekçeler:

  • Her adımda ortalama 8,5 ekliyoruz.
  • 1.000.000'a ulaşmak için bu adımların 117.647'sine ihtiyacımız var.
  • Bu sayıda adımdan daha azını gerçekleştirme olasılığı

    sum(n=0..117,646) (299,999/300,000)^n * 1/300,000
    

    hangi değerlendirir 0.324402 . Bu nedenle, vakaların yaklaşık üçte ikisinde, daha fazla 117.647 adım atacağız ve her biri 1.000.000.

  • (Bunun tam bir olasılık olmadığını unutmayın, çünkü bu ortalama 8.5 hakkında bir miktar dalgalanma olacak, ancak% 50'ye ulaşmak için 117.646 ila yaklaşık 210.000 adımın çok ötesine geçmemiz gerekiyor.)
  • Şüpheniz varsa, fesih olasılığının paydasını kolayca patlatabiliriz, 9e9 herhangi bir bayt (ancak yıllarca çalışma süresi) eklemeden .

... veya 11 bayt mı?

Son olarak, 11 baytlık bir sürüm var, bu da PRNG dönemiyle sınırlı değil, her seferinde bellekte neredeyse bitecek. Her yinelemede (zaman damgasına dayalı olarak) yalnızca bir rasgele sayı oluşturur ve bunu hem arttırma hem de sonlandırma için kullanır. Her yinelemeden elde edilen sonuçlar yığın üzerinde kalır ve yalnızca sonunda toplanır. Dennis'e bu fikir için teşekkürler:

{esmr(}h]:+

Kuralların gerçek bir rastgele sayı üreteci gerektirip gerektirmediğini görmek için soruya bir yorum ekledim, ancak bilgiçliği takdir edeceğinizi tahmin ettim. Buradaki rastgele kaynağınız sahte sözde mi? Bu, olası çıktı setinin boyutunu en fazla PRNG döneminizle sınırlar, değil mi?
trichoplax

(Basit zarafet ne olursa olsun +1)
trichoplax

Evet şimdiye kadar tahmin ediyorum. Birisi bu sorun olmadan bir cevap
gönderirse

OP, rasgele sayı üretecinizin ister gerçek olsun ister gerçek bir sayı üreteci olduğunu varsayabileceğinizi belirttiğini görüyoruz - bu yüzden artık gereksiz ... :)
trichoplax

KmrBir dönemin toplamı hala her zaman dönemden daha büyük pozitif bir sayıdır. Ve bu durumda mümkün olan her sayıyı üretemez.
jimmy23013

11

Java, 133 149

void f(){String s=x(2)<1?"-":"";for(s+=x(9)+1;x(50)>0;s+=x(10));System.out.print(x(9)<1?0:s);}int x(int i){return new java.util.Random().nextInt(i);}

Örnek çıktılar

-8288612864831065123773
0
660850844164689214
-92190983694570102879284616600593698307556468079819964903404819
3264

Ungolfed

void f() {
    String s = x(2)<1 ? "-" : "";       // start with optional negative sign
    s+=x(9)+1;                          // add a random non-zero digit
    for(; x(50)>0; )                    // with a 98% probability...
        s+=x(10)                        // append a random digit
    System.out.print(x(9)<1 ? 0 : s);   // 10% chance of printing 0 instead
}

int x(int i) {
    return new java.util.Random().nextInt(i);
}

Eski cevap (kural değişikliğinden önce)

void f(){if(Math.random()<.5)System.out.print('-');do System.out.print(new java.util.Random().nextInt(10));while(Math.random()>.02);}

Her ikiniz de
haklısınız

@Optimizer Redone.
Ypnypn

İkili değişmez değerleri kullanıyorsanız -,.
TheNumberOne

4

Mathematica - 47

Round@RandomVariate@NormalDistribution[0,15*^5]

Temel olarak sadece 1500000'e eşit varyansla normal dağılım kullanarak rastgele sayı üretin. Bu,% 49.5015 olasılıkla -10 ^ 6 ve 10 ^ 6 arasında bir tamsayı üretecektir.


"Bu,% 50.4985 olasılıkla -10 ^ 6 ile 10 ^ 6 arasında bir tamsayı üretecektir." - bu yeterli değil. Spesifikasyonu yanlış anladın mı? Belki de varyans olarak 10 ^ 7 kullanmak istediniz?
John Dvorak

@JanDvorak Yanlış olasılık, üzgünüm. Şimdi doğru olanı.
swish

Bunun Mathematica'da uygulanması tüm tam sayıları gerçekten kapsıyor mu?
Kaynağa erişimim

@githubphagocyte Mevcut hassasiyete bağlı olacaktır.
swish

4
Demek istediğim, herhangi bir kesinliğin belirtilmesi bundan daha büyük sayıları hariç tutacaktır. Çalışabilmesinin tek yolu, sınırsız hassasiyet belirleyebilmenizdir.
trichoplax

4

Python 2, 75 69 bayt

from random import*;s=0;j=randrange
while j(12):s=s*9+j(-8,9)
print s

Ortadaki while döngüsünün tüm tamsayıları üretebildiğini (sıfıra doğru yönlendirilmiş olsa da) kontrol etmek önemsizdir. "12" ± 10 aşan sayı kabaca yarısı olduğu şekilde seçilir 6 .


Eski çözüm:

Python 2, 44 bayt

Göre Mathematica'da çözeltisi .

from random import*;print int(gauss(0,8**7))

Gerçekten işe yaramıyor çünkü Python'un floatkesin bir hassasiyeti var.


Bu tüm tamsayıları üretemeyecektir, çünkü sözde rasgele sayı üretecinin sınırlı miktarda dahili durumu vardır. Belgelere göre Python Mersenne Twister'ı kullanıyor, bu yüzden devlet oldukça büyük. Ancak sonsuz değildir, bu nedenle tüm tamsayıların yalnızca sınırlı bir alt kümesini üretebilir.
starblue

@starblue: OP'den: "Durumunuz olmasa bile, dilinizin rasgele sayı üretecinin gerçek bir rasgele sayı üreteci olduğunu varsayabilirsiniz."
kennytm

3

Yakut, 70

f=->{m=10**6
r=rand -m..m
r<1?(r>-5e5??-:'')+r.to_s+f[][/\d+/]:r.to_s}

Çok büyük sayılar üretmeyi mümkün kılmak için, sayıyı bir String , bir lambda'dan . Buna izin verilmiyorsa, puts f[]bir işlev yerine bir program yapmak için 8 karakter (fazladan ) sayın .

açıklama

Arasında bir sayı üret -1,000,000ve 1,000,000. Sayı 1veya daha büyükse, sayı a olarak döndürülür String.

Sayı küçükten küçükse 1, sayıyı sayı aralığının dışında döndürmek için işlev yinelemeli olarak çağrılır. Negatif sayıların da üretilebildiğinden emin olmak için, ilk sayı daha büyükse -sonuçta a öneki eklenir .String-500,000

Umarım meydan okumayı doğru anladım!


3

R, 38

library(Rmpfr)
round(rnorm(1,2e6,1e6))

Gauss dağılımından rastgele seçilen ortalama 2.000.000 ve standart sapma 1.000.000 ile çekilişler, böylece çekimlerin yaklaşık 2/3'ü 1.000.000 ve 3.000.000 arasında olacaktır. Dağıtım sınırsızdır, bu nedenle teoride bu herhangi bir tamsayı üretebilir. Rmpfr paketi, R'nin yerleşik çift şamandıralarının yerini keyfi bir hassasiyetle değiştirir.


Evet, teknik özellikleri yanlış okuduğumu fark ettim. Ve Mathematica ile makine hassasiyeti ile aynı sınırlamalara sahip olduğunu hayal ediyorum
shadowtalker

Hmm in that case I'm not sure. I'll have to look into it; consider this answer "on hold" for now
shadowtalker

@MartinBüttner fixed I think
shadowtalker

Interesting. I don't think you need the whole sample(c(1,-1),1) think though. Just centering at 1e6 should be enough..
Martin Ender

@MartinBüttner oh it doesn't need to be 50% at both ends? That wasn't clear
shadowtalker

2

Perl, 53 characters

print"-"if rand>.5;do{print int rand 10}while rand>.1

I certainly don't see any reason to work with integers when printing one :)

Has equal probability of printing a number with or without a leading "-".

Prints a 1-digit number 10% of the time, a 2-digit number 9% of the time, a 3-digit number 8.1% of the time, a 4-digit number 7.29% of the time, a 5-digit number 6.56% of the time, a 6-digit number 5.9% of the time, etc. Any length is possible, with decreasing probability. The one-through-five digit numbers account for about 41.5% of output cases, and the number 1,000,000 (or -1,000,000) only 6-millionths of a percent, so the output number will be outside of the range -1,000,000 through 1,000,000 about 54.6% of the time.

Both "0" and "-0" are possible outputs, which I hope is not a problem.


Doesn't this print "numbers" like -00000000167? That's not really an integer.
isaacg

1
@isaacg I don't see why that is not an integer .
Optimizer

2
@Optimizer It is, but the OP has explicitly forbidden leading 0.
Martin Ender

You could generate a random non-zero leading digit before the loop, from -9 to +9. print int(rand(20)-10)||1. I need a way to generate 0 as an output, though. Maybe ||die 0, if the trailing garbage after the zero is allowed. Else need a short way to print the zero and exit without further output if int(rand(20)-10)==0.
Peter Cordes

@PeterCordes agreed, that's a decent approach but I don't feel like writing it and I don't think it would be competitive length-wise. Feel free to submit it on your own :)
hobbs

2

Perl, 114 Chars

use Math::BigInt;sub r{$x=Math::BigInt->new(0);while(rand(99)!=0){$x->badd(rand(2**99)-2**98);}print($x->bstr());}

Breakdown:

use Math::BigInt;               -- include BigIntegers
  sub r{                        -- Define subroutine "r"
    $x=Math::BigInt->new(0);    -- Create BigInteger $x with initial value "0"
      while(rand(99)!=0){       -- Loop around until rand(99) equals "0" (may be a long time)
        $x->badd(               -- Add a value to that BigInt
          rand(2**99)-2**98);   -- Generate a random number between -2^98 and +2^98-1
        }print($x->bstr());}    -- print the value of the BigInt

The probability of getting a value between -1.000.000 and 1.000.000 are tending towards zero BUT it is possible.

Note: This subroutine may run for a long time and error out with an "Out of Memory!" error but it's technically generating any integer as stated in the question.

Perl, 25

sub r{rand(2**99)-2**98;}

Generates a random integer within the range of +/-2^99.

Breakdown

sub r{                    -- Define subroutine "r"
     rand(2**99)          -- Generate a random integer between 0 and 2^99
                -2**98;}  -- Subtract 2^98 to get negative values as well

Tested with 1 million samples:

~5 are inside the range of +/-1.000.000
~999.995 are outside that range
= a probability of ~99,99% of generating an integer outside that range.
Compare that number to the probability of 2.000.000 in 2^99: It is approx. the same.

This meets all rules:

  • 1 integer
  • any integer is possible
  • at least 50% (in my case 99,99%) of all generated integers are outside the range of +/-1.000.000.

This works because the underlying random number generator defines equal probability to every bit that is generated, thus doing that on generated integers as well.
Every integer has a probability of 1/2^99 to be generated.

Edit:

I had to increase the exponent so that larger integers are being generated. I have chosen 99 because it keeps the code as short as possible.


Didn't we agree that there should not be any upper/lower bounds ? For instance, the integer 2^31 + 1 has 0 probability, breaking rule 2
Optimizer

@Optimizer for me an integer is defined as in many programming languages: a number within the bounds of -2^31 and +2^31-1 (32bits). You can easily increase the exponents if you'd like to generate larger integers but it may fail depending on the implementation of Perl.
GiantTree

I just saw that that ridiculously big integer has to be generated as well. I'll edit my code quickly.
GiantTree

@MartinBüttner I tried my best to meet the spec of the question. It's just not possible for me (at least not without help) to generate infinitely large integers. Perl's largest integer is about 1.7e308 which is a limit I cannot control.
GiantTree

@MartinBüttner Both are possible but eg. the string would overflow after 2gb of data making it finite again. It's hard to say that a number should be infinitely large if there are issues with memory. I'll come up with a different approach soon using BigInts. Also the integer does not overflow at 1.7e308 it just gets converted to infite (1.#INF to be exact)
GiantTree

2

C#, 126 107 bytes

string F(){var a=new System.Random();var b=a.Next(-1E6,1E6+1)+"";while(a.Next(1)>0)b+=a.Next(10);return b;}

Ungolfed:

string F()
{
    System.Random rand = new System.Random();
    string rtn = rand.Next(-1E6, 1E6 + 1) + "";
    while (rand.Next(1) > 0)
         rtn += a.Next(10);
    return rtn;
}

Chance to generate a number of n digits is 1/2^(n-10), which is greater than 0 for all positive n, and 1/2 for n=11. Also creates leading zeros, which do not seem to be disallowed in the original question or any of its comments.


When using using System;, you don't need System.Random twice, but just Random, right?
Charlie

@Charlie This is a function, so I can't use using statements. It would only save 1 char anyways.
LegionMammal978

1
You can save 1 char by removing the space at -1E6, 1E6+1.
ProgramFOX

2

Perl, 62 bytes

print $n=int rand(20)-10;while($n&&rand>.1){print int rand 10}

I had the same idea as @Hobbs, of generating a digit at a time, but his code didn't satisfy the added no-leading-zeros requirement. Generating the first digit instead of just the sign solved that. And unless there's a shorter way to exit if we printed a zero, or a shorter way to generate the leading -9 to 9, this should do it for size.

In a shell loop: while perl -e '...'; do echo;done |less

I think this is one of the shortest that doesn't require infinite RAM to satisfy the problem. As a bonus, the output is isn't strongly biased towards anything, and runtime is very fast.

I tried using bitwise and to save a character in the while condition, but I think this ends up being true more often, so the loop ends sooner. Would need more chars to adjust other things to counter that, to maintain the probability of generating abs(output) > 1M.


Nice, you squeezed out some things that I wouldn't have thought of :)
hobbs

1

Javascript (73)

This solution uses that you can construct a number with base n by multiplying the previous number with n and adding a digit in base n. We have an additional ..?..:.. in there to be able to create all negative integers. The following code should be tested in a browser console.

b=Math.round;c=Math.random;x=0;while(b(c()*99)){x*=b(c())?2:-2;x+=b(c())}

The probability to get an integer >= 2^1 (or <= -(2^1)) is equal to the chance that the loop is ran 2 times. The chance of that happening is (98/99)^2. The chance of getting a number that is greater than 2^20 (or <= -(2^20)) is therefore (98/99)^21 = 0.808 or 81%. This is all in theory though, and assuming that Math.random is truely random. It obviously isn't.


Snippet testing this code. Also in a more readable fashion.


1
The OP has now confirmed that you can assume that your PRNG is truly random, even if it isn't.
trichoplax

1

GolfScript, 20 bytes

0{)8.?rand}do.2&(*4/

Yeah, this one is also kind of slow.

Compared to languages like CJam and Pyth, GolfScript suffers from a verbose random number generation keyword (rand). To overcome this handicap, I needed to find a way to use it only once.

This code works by repeatedly picking a random number between 0 and 88−1 = 16,777,215 inclusive, and incrementing a counter until the random number happens to be 0. The resulting counter value has a geometric distribution with a median approximately -1 / log2(1 − 1/88) ≈ 11,629,080, so it meets the "over 1,000,000 at least 50% of the time" test.

Alas, the random number thus generated is always strictly positive. Thus, the extra .2&(*4/ part is needed to let it become negative or zero. It works by extracting the second-lowest bit of the number (which is thus either 0 or 2), decrementing it to make it -1 or 1, multiplying it with the original number, and dividing the result by 4 (to get rid of the lowest two bits, which are now correlated with the sign, and also to allow the result to become zero). Even after the division by 4, the absolute value of the random number still has a median of -1 / log2(1 − 1/88) / 4 ≈ 2,907,270, so it still passes the 50% test.


1

JavaScript, 81 bytes

This code fulfills all the rules:

  • Output any integer with positive probability
  • Output integers outside the range of +/-1000000 with at least 50% probability
  • No leading 0 in the output

As a bonus, the algorithm runs with a time complexity of O(log10n) so it returns the integer almost instantly.

for(s="",r=Math.random;r()>.1;s+=10*r()|0);r(s=s.replace(/^0*/,"")||0)<.5?"-"+s:s

This assumes an REPL environment. Try running the above code in your browser's console, or use the stack snippet below:

D.onclick = function() {
  for(s="", r=Math.random;r()>.1; s+=10*r()|0);
  P.innerHTML += (r(s=s.replace(/^0*/,"") || 0) <.5 ?"-" + s : s) + "<br>"
}
<button id=D>Generate a random number</button><pre id=P></pre>

Algorithm:

  • Keep appending random digits to string s until a Math.random() > 0.1.
  • Based on Math.random() > 0.5, make the number negative (by prepending the string s with -).

This algorithm does not have a uniform distribution across all integers. Integers with higher digit count are less probable than the lower ones. In each for loop iteration, there is a 10% chance that I will stop at the current digit. I just have to make sure that I stop after 6 digits more than 50% of the time.

This equation by @nutki explains the maximum value of stopping chance percentage based on the above condition:

1 - 50%^(1/6) ≈ 0.11

Thus 0.1 is well within range to satisfy all the three rules of the question.


There are a few things that confuse me about this answer. Have you assumed that Math.random() generates a uniform distribution of random numbers, because the spec states that it is implementation dependent. Assuming that it is a uniform distribution, P(Math.random()>0.1)=0.9 so there is a huge probability that it will terminate between each iteration. An implementation of your algorithm run on Firefox 34.0 Ubuntu gives me a probability of ~0.47 (<0.5) every time that I test it: jsfiddle.net/WK_of_Angmar/dh8gq4pb
Wk_of_Angmar

Also, how have you managed to calculate a time complexity for an algorithm without an input?
Wk_of_Angmar

1

TI-BASIC, 14 bytes

1-2int(2rand:randNorm(AnsE6,9

Similar to @ssdecontrol's R answer, this draws from the Gaussian distribution with mean -1,000,000 or 1,000,000, chosen randomly, and standard deviation 9. The distribution is unbounded so in theory this can generate any integer.

Explanation:

1-2int(2rand     - get a random integer 0 or 1, then multiply by 2 and subtract 1
:                - this gives the number 1 or -1 (with equal probability) to Ans
randNorm(AnsE6,9 - displays Gaussian distribution with mean (Ans * 1,000,000) and std. dev. 9

But can it generate "2" or "-2"?
kennytm


1
OK read the code wrongly (thought : means "print" due to how the explanation is presented). But can it generate numbers more than 20 digits?
kennytm

Any arbitrary long integer is possible as an output ? Isn't this limited by the range of randNorm ?
Optimizer

"The distribution is unbounded so in theory this can generate any integer." There is no range.
Timtech

1

Bash, 66

LANG=C sed -r '/^-?(0|[1-9][0-9]*)$/q;s/.*/5000000/;q'</dev/random

It almost always prints 5000000. But if it found a valid number in /dev/random, it will print that number instead.

And this one is faster:

LANG=C sed -r '/^-?(0|[1-9][0-9]*)$/q;s/.*/5000000/;q'</dev/urandom

1
@Optimizer It is supposed to be slow. That's because it is a real random source. But you can test it with /dev/urandom which is less random.
jimmy23013

@Optimizer How would that be taking manual input? It's reading a file, but everything's a file.
Nit

@Optimizer I simply don't understand the point you're going for.
Nit

reading from /dev/urandom in a shell script is basically the same as calling rand() in other languages. Although if you're really using bash, not POSIX sh, you can get random numbers from echo $RANDOM. wiki.ubuntu.com/DashAsBinSh gives hexdump /dev/urandom as an equivalent for bare-POSIX-minimum /bin/dash.
Peter Cordes

1

C++, 95 bytes

void f(){int d=-18,s=-1;while(s<9){d=(rand()%19+d+9)%10;cout<<d;s=9-rand()%10*min(d*d+s+1,1);}}

Expanded:

void f() {
    int d=-18,s=-1;
    while(s<9) {
        d=(rand()%19+d+9)%10;
        cout<<d;
        s=9-rand()%10*min(d*d+s+1,1);
    }
}

Explanation:

The function keeps on printing consecutive random digits until a random valued switch takes the required value to stop the function. d is the variable that keeps the value of the next digit to be printed. s is the switch variable that takes random integer values in the interval [0, 9], if s == 9 then no more digits are printed and the funtion ends.

The variables d and s are initialized in order to give special treatment to the first digit (taking it from the interval [-9, 9] and if the first digit is zero then the function must end to avoid leading zeroes). The value of d could be assigned as d=rand()%10 but then the first digit couldn't be negative. d is assigned instead as d=(rand()%19+d+9)%10 and initialized at -18 so the first value of d will range from [-9, 9] and the next values will always range from [0, 9].

The variable s ranges randomly from [0, 9], and if s equals 9, the function ends, so after printing the first digit the next one will be printed with a probability of 90% (assuming rand() is truly random, and in order to satisfy the third condition). s could be easily assigned as s=rand()%10, however, there is an exception, if the first digit is zero, the function must end. In order to handle such exception, s has been assigned as s=9-rand()%10*min(d*d+s+1,1) and initialized as -1. If the first digit is zero, the min will return 0 and s will equal to 9-0=9. s variable's assignment will always range from [0, 9], so the exception can only occur at the first digit.

Characteristics (assuming rand() is truly random)

  • The integer is printed digit by digit, with a fixed probability of 90% of printing another digit after printing the last one.

  • 0 is the integer with highest chance of being printed, with a probability of aproximately 5.2%.

  • The probability of printing an integer on the interval [-10^6, 10^6] is aproximately 44% (the calculation is not written here).

  • Positive and negative integers are printed with the same probability (~47.4%).

  • Not all digits are printed with the same probability. For example: in the middle of printing the integer, if the last digit was 5, the digit 3 will have a slightly lower chance of being printed next. In general, if the last digit was d, the digit (d+18)%10 will have a slightly lower chance of being printed next.

Example outputs (10 executions)

-548856139437
7358950092214
507
912709491283845942316784
-68
-6
-87614261
0
-5139524
7

Process returned 0 (0x0)   execution time : 0.928 s
Press any key to continue.

1

Bash, 42 bytes

printf "%d\n" 0x$(xxd -p -l5 /dev/random)
/dev/random on OSX is just random bytes, and xxd -p -l5 converts 5 of the ascii characters to hex, and printf turns it into decimal format.


0

Pyth, 11 bytes

WOyG~ZtOT)Z

Note: this program will probably crash with a memory error on any real computer. To test it, try replacing G with a shorter string, such as in this code, which generates numbers averaging around 28000:

pyth -c 'WOy"abcdefghijklm"~ZtOUT)Z'

This code loops, adding a random number from -1 to 8 to Z, with a 2^-26 probability of exiting the loop on each repetition. The 2^-26 probability is attained by selecting a random element (O) of the set of all subsets (y) of the alphabet (G).

Technical details & justification:

The probability 2^-26 is derived from two facts: y, when called on sequences, is the power-set function, an constructs the list of all subsets of the input. Since the input, G, is 26 characters long, this power-set, yG has 2^26 entries. OyG selects a random element from those 2^26 entries. Exactly one of those entries, the empty string, will evaluate as falsy when passed to W, the while loop. Therefore, there is a 2^-26 probability of exiting the loop each time.

In any fixed number of loop cycles K, the probability of getting the number K*3.5 + m and getting K*3.5 - m are equal, because each sequences of addends that achieves one total can be inverted, -1 -> 8, 0 -> 7, etc., to achieve the other. Additionally, numbers closer to K*3.5 are clearly more likely than numbers farther away. Thus, if K > 2000000/3.5 = 571428.5 the probability of getting a number over 1000000 is greater than 75%, because some of the results above that number can be put into a one-to-one correspondence with all of the results below that number, and the upper less-than-half, can be put into a one-to-one correspondence with those under 1000000. The probability of getting at least 571429 loops is (1-2^-26)^571429, which is no less than (1-2^-26 * 571429), the expected number of times leaving the loop over the first 571429 tries, which is 99.1%. Thus, on 99.1% or more of trials, there is a 75% or more chance of getting at least 1000000, so there is more than a 50% chance of getting over 1000000.

This code relies on a behavior of O where a bug was accidentally introduced 3 days ago and was fixed today. It should work on any version of Pyth 3 from before Dec 22nd, or after today. The following code is equivalent, and has always worked:

WOyG~ZtOUT)Z

What happened to the online compiler ?
Optimizer

@Optimizer Issues with the website, I'll work on it.
isaacg

Ah.. cool. Wanted to work on the Pyth translation of my CJam answer yesterday and found that it gives 404.
Optimizer

0

Java, 113 bytes

void g(){String a=Math.random()>0?"10":"01";for(;Math.random()>0;)a+=(int)(Math.random()*2);System.out.print(a);}

This program prints a binary number to standard output stream. You might have to wait a while because the probability of it ending the number (or it being positive) is approximately 0. The idea that the absolute value of a number generated is less than 1 million is amusing, yet possible.

Ungolfed:

void g(){
    String a=Math.random()>0?"10":"01";             //Make sure there are no trailing zeroes.
    for(;Math.random()>0;)a+=(int)(Math.random()*2);//Add digits
    System.out.print(a);                            //Print
}

Sample output: Will post when a number is done being generated.


0

Java (JDK), 140 127 bytes

()->{int i;var o=System.out;for(o.print(i=(int)(19*Math.random())-10);i!=0&Math.random()<.9;)o.print((int)(11*Math.random()));}

-13 bytes by sneaking more logic into the loop header - thanks to @ceilingcat

Try it online!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.