I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

Pseudo-random numbers/Middle-square method

From Rosetta Code
Task
Pseudo-random numbers/Middle-square method
You are encouraged to solve this task according to the task description, using any language you may know.
Middle-square_method Generator
The Method

To generate a sequence of n-digit pseudorandom numbers, an n-digit starting value is created and squared, producing a 2n-digit number. If the result has fewer than 2n digits, leading zeroes are added to compensate. The middle n digits of the result would be the next number in the sequence and returned as the result. This process is then repeated to generate more numbers.

Pseudo code
var seed = 675248
function random()
    var s = str(seed * seed) 'str: turn a number into string
    do while not len(s) = 12
        s = "0" + s          'add zeroes before the string
    end do
    seed = val(mid(s, 4, 6)) 'mid: string variable, start, length
                             'val: turn a string into number
    return seed
end function
Middle-square method use
for i = 1 to 5
    print random()
end for
Task
  • Generate a class/set of functions that generates pseudo-random

numbers (6 digits) as shown above.

  • Show the first five integers generated with the seed 675248 as shown above.
  • Show your output here, on this page.


ALGOL 68[edit]

Uses (long) integers.

BEGIN # generate random numbers by the middle-square method #
INT seed := 675248;
# returns the next middle-square random number #
PROC ms random = INT: seed := SHORTEN( ( ( LONG INT( seed ) * LONG INT( seed ) ) OVER 1000 ) MOD 1 000 000 );
# test the ms random procedure #
FOR i TO 5 DO
print( ( " ", whole( ms random, 0 ) ) )
OD
END
Output:
 959861 333139 981593 524817 432883

AppleScript[edit]

on newGenerator(n, seed)
script generator
property seed : missing value
property p1 : 10 ^ (n div 2)
property p2 : 10 ^ n
 
on getRandom()
set seed to seed * seed div p1 mod p2
return seed div 1
end getRandom
end script
 
set generator's seed to seed mod (10 ^ n)
return generator
end newGenerator
 
local generator, output
set generator to newGenerator(6, 675248)
set output to {}
repeat 5 times
set end of output to generator's getRandom()
end repeat
return output
Output:
{959861, 333139, 981593, 524817, 432883}

AWK[edit]

 
# syntax: GAWK -f PSEUDO-RANDOM_NUMBERS_MIDDLE-SQUARE_METHOD.AWK
BEGIN {
seed = 675248
srand(seed)
for (i=1; i<=5; i++) {
printf("%2d: %s\n",i,main())
}
exit(0)
}
function main( s) {
s = seed ^ 2
while (length(s) < 12) {
s = "0" s
}
seed = substr(s,4,6)
return(seed)
}
 
Output:
 1: 959861
 2: 333139
 3: 981593
 4: 524817
 5: 432883

C[edit]

#include<stdio.h>
long long seed;
long long random(){
seed = seed * seed / 1000 % 1000000;
return seed;
}
int main(){
seed = 675248;
for(int i=1;i<=5;i++)
printf("%lld\n",random());
return 0;
}
Output:

959861 333139 981593 524817 432883

C++[edit]

#include <exception>
#include <iostream>
 
using ulong = unsigned long;
 
class MiddleSquare {
private:
ulong state;
ulong div, mod;
public:
MiddleSquare() = delete;
MiddleSquare(ulong start, ulong length) {
if (length % 2) throw std::invalid_argument("length must be even");
div = mod = 1;
for (ulong i=0; i<length/2; i++) div *= 10;
for (ulong i=0; i<length; i++) mod *= 10;
state = start % mod;
}
 
ulong next() {
return state = state * state / div % mod;
}
};
 
int main() {
MiddleSquare msq(675248, 6);
for (int i=0; i<5; i++)
std::cout << msq.next() << std::endl;
return 0;
}
Output:
959861
333139
981593
524817
432883

CLU[edit]

middle_square = cluster is seed, next
rep = null
own state: int
 
seed = proc (s: int)
state := s
end seed
 
next = proc () returns (int)
state := (state ** 2) / 1000 // 1000000
return(state)
end next
end middle_square
 
start_up = proc ()
po: stream := stream$primary_output()
middle_square$seed(675248)
for i: int in int$from_to(1, 5) do
stream$putl(po, int$unparse(middle_square$next()))
end
end start_up
Output:
959861
333139
981593
524817
432883

COBOL[edit]

       IDENTIFICATION DIVISION.
PROGRAM-ID. MIDDLE-SQUARE.
 
DATA DIVISION.
WORKING-STORAGE SECTION.
01 STATE.
03 SEED PIC 9(6) VALUE 675248.
03 SQUARE PIC 9(12).
03 FILLER REDEFINES SQUARE.
05 FILLER PIC 9(3).
05 NEXT-SEED PIC 9(6).
05 FILLER PIC 9(3).
 
PROCEDURE DIVISION.
BEGIN.
PERFORM SHOW-NUM 5 TIMES.
STOP RUN.
 
SHOW-NUM.
PERFORM MAKE-RANDOM.
DISPLAY SEED.
 
MAKE-RANDOM.
MULTIPLY SEED BY SEED GIVING SQUARE.
MOVE NEXT-SEED TO SEED.
Output:
959861
333139
981593
524817
432883

F#[edit]

 
// Pseudo-random numbers/Middle-square method. Nigel Galloway: January 5th., 2022
Seq.unfold(fun n->let n=n*n%1000000000L/1000L in Some(n,n)) 675248L|>Seq.take 5|>Seq.iter(printfn "%d")
 
Output:
959861
333139
981593
524817
432883

Factor[edit]

Translation of: Phix
Works with: Factor version 0.99 2021-06-02
USING: kernel math namespaces prettyprint ;
 
SYMBOL: seed
675248 seed set-global
 
: rand ( -- n ) seed get sq 1000 /i 1000000 mod dup seed set ;
 
5 [ rand . ] times
Output:
959861
333139
981593
524817
432883

FreeBASIC[edit]

Dim Shared seed As Integer = 675248
Dim i As Integer
Declare Function Rand As Integer
For i = 1 To 5
Print Rand
Next i
Sleep
 
Function Rand As Integer
Dim s As String
s = Str(seed ^ 2)
Do While Len(s) <> 12
s = "0" + s
Loop
seed = Val(Mid(s, 4, 6))
Rand = seed
End Function
 

J[edit]

(_6{._3}.])&.:(10&#.^:_1)@(*~) ^: (>:i.6) 675248
Output:
959861 333139 981593 524817 432883 387691

jq[edit]

Works with gojq, the Go implementation of jq

The proposed PRNG hardly deserves the name and so this entry avoids it.

# Input: a positive integer
# Output: the "middle-square"
def middle_square:
(tostring|length) as $len
| (. * .)
| tostring
| (3*length/4|ceil) as $n
| .[ -$n : $len-$n]
| if length == 0 then 0 else tonumber end;
 
# Input: a positive integer
# Output: middle_square, applied recursively
def middle_squares:
middle_square | ., middle_squares;
 
limit(5; 675248 | middle_squares)
Output:

As expected.

Julia[edit]

const seed = [675248]
 
function random()
s = string(seed[] * seed[], pad=12) # turn a number into string, pad to 12 digits
seed[] = parse(Int, s[begin+3:end-3]) # take middle of number string, parse to Int
return seed[]
end
 
# Middle-square method use
 
for i = 1:5
println(random())
end
 
Output:
959861
333139
981593
524817
432883

Perl[edit]

#!/usr/bin/perl
 
use strict; # https://rosettacode.org/wiki/Pseudo-random_numbers/Middle-square_method
use warnings;
 
sub msq
{
use feature qw( state );
state $seed = 675248;
$seed = sprintf "%06d", $seed ** 2 / 1000 % 1e6;
}
 
print msq, "\n" for 1 .. 5;
Output:
959861
333139
981593
524817
432883

Phix[edit]

You don't actually have to use strings, but should you so desire the commented-out line gives exactly the same results. Output matches Python.

with javascript_semantics
integer seed = 675248
function random()
    seed = remainder(floor(seed*seed/1000),1e6)
--  seed = to_integer(sprintf("%012d",seed*seed)[4..9])
    return seed
end function
for i=1 to 5 do
    ?random()
end for

PureBasic[edit]

Procedure.i MSRandom()
Static.i seed=675248
seed = (seed*seed/1000)%1000000
ProcedureReturn seed
EndProcedure
 
If OpenConsole()
For i=1 To 5 : PrintN(Str(i)+": "+Str(MSRandom())) : Next
Input()
EndIf
Output:
1: 959861
2: 333139
3: 981593
4: 524817
5: 432883

Python[edit]

seed = 675248
def random():
global seed
s = str(seed ** 2)
while len(s) != 12:
s = "0" + s
seed = int(s[3:9])
return seed
for i in range(0,5):
print(random())
 
Output:
959861
333139
981593
524817
432883

Raku[edit]

sub msq {
state $seed = 675248;
$seed = $seed² div 1000 mod 1000000;
}
 
say msq() xx 5;
Output:
(959861 333139 981593 524817 432883)

Red[edit]

Translation of: Phix
Red[]
seed: 675248
rand: does [seed: to-integer (seed * 1.0 * seed / 1000) % 1000000] ; multiply by 1.0 to avoid integer overflow (32-bit)
loop 5 [print rand]
Output:
959861
333139
981593
524817
432883

UNIX Shell[edit]

Works with: zsh
seed=675248
random(){
seed=`expr $seed \* $seed / 1000 % 1000000`
return seed
}
for ((i=1;i<=5;i++));
do
random
echo $?
done
Output:

The same as Python's

VBA[edit]

See Visual Basic

Visual Basic[edit]

Translation of: FreeBASIC
Works with: Visual Basic version 5
Works with: Visual Basic version 6
Option Explicit
Dim seed As Long
Sub Main()
Dim i As Integer
seed = 675248
For i = 1 To 5
Debug.Print Rand
Next i
End Sub
Function Rand() As Variant
Dim s As String
s = CStr(seed ^ 2)
Do While Len(s) <> 12
s = "0" + s
Loop
seed = Val(Mid(s, 4, 6))
Rand = seed
End Function
Output:

As expected.

Wren[edit]

var random = Fn.new { |seed| ((seed * seed)/1e3).floor % 1e6 }
 
var seed = 675248
for (i in 1..5) System.print(seed = random.call(seed))
Output:
959861
333139
981593
524817
432883

XPL0[edit]

real Seed;
func Random;
[Seed:= Floor(Mod(Seed*Seed/1e3, 1e6));
return fix(Seed);
];
 
int N;
[Seed:= 675248.;
for N:= 1 to 5 do
[IntOut(0, Random); ChOut(0, ^ )];
]
Output:
959861 333139 981593 524817 432883