Pseudo-random numbers/Middle-square method: Difference between revisions
No edit summary |
(add task to arm assemble raspberry pi) |
||
Line 97: | Line 97: | ||
{{output}} |
{{output}} |
||
<lang applescript>{959861, 333139, 981593, 524817, 432883}</lang> |
<lang applescript>{959861, 333139, 981593, 524817, 432883}</lang> |
||
=={{header|ARM Assembly}}== |
|||
{{works with|as|Raspberry Pi <br> or android 32 bits with application Termux}} |
|||
<lang ARM Assembly> |
|||
/* ARM assembly Raspberry PI or android with termux */ |
|||
/* program pRandom.s */ |
|||
/* REMARK 1 : this program use routines in a include file |
|||
see task Include a file language arm assembly |
|||
for the routine affichageMess conversion10 |
|||
see at end of this program the instruction include */ |
|||
/* for constantes see task include a file in arm assembly */ |
|||
/************************************/ |
|||
/* Constantes */ |
|||
/************************************/ |
|||
.include "../constantes.inc" |
|||
/*********************************/ |
|||
/* Initialized data */ |
|||
/*********************************/ |
|||
.data |
|||
sMessResult: .asciz " @ \n" |
|||
szCarriageReturn: .asciz "\n" |
|||
iSeed: .int 675248 |
|||
/*********************************/ |
|||
/* UnInitialized data */ |
|||
/*********************************/ |
|||
.bss |
|||
sZoneConv: .skip 24 |
|||
/*********************************/ |
|||
/* code section */ |
|||
/*********************************/ |
|||
.text |
|||
.global main |
|||
main: @ entry of program |
|||
ldr r0,iAdriSeed |
|||
ldr r3,[r0] |
|||
mov r2,#5 |
|||
1: |
|||
mov r0,r3 |
|||
bl computePseudo |
|||
mov r3,r0 |
|||
ldr r1,iAdrsZoneConv |
|||
bl conversion10 @ call décimal conversion |
|||
ldr r0,iAdrsMessResult |
|||
ldr r1,iAdrsZoneConv @ insert conversion in message |
|||
bl strInsertAtCharInc |
|||
bl affichageMess @ display message |
|||
subs r2,r2,#1 |
|||
bgt 1b |
|||
100: @ standard end of the program |
|||
mov r0, #0 @ return code |
|||
mov r7, #EXIT @ request to exit program |
|||
svc #0 @ perform the system call |
|||
iAdrszCarriageReturn: .int szCarriageReturn |
|||
iAdrsMessResult: .int sMessResult |
|||
iAdrsZoneConv: .int sZoneConv |
|||
iAdriSeed: .int iSeed |
|||
/***************************************************/ |
|||
/* compute pseudo random number */ |
|||
/***************************************************/ |
|||
/* r0 contains the number */ |
|||
computePseudo: |
|||
push {r1-r2,lr} @ save registers |
|||
mov r2,r0 |
|||
umull r0,r1,r2,r2 |
|||
ldr r2,idiv |
|||
bl division32R |
|||
ldr r2,idiv2 |
|||
bl division32R |
|||
mov r0,r2 |
|||
pop {r1-r2,pc} @ restaur registers |
|||
idiv: .int 1000 |
|||
idiv2: .int 1000000 |
|||
/***************************************************/ |
|||
/* division number 64 bits in 2 registers by number 32 bits */ |
|||
/***************************************************/ |
|||
/* r0 contains lower part dividende */ |
|||
/* r1 contains upper part dividende */ |
|||
/* r2 contains divisor */ |
|||
/* r0 return lower part quotient */ |
|||
/* r1 return upper part quotient */ |
|||
/* r2 return remainder */ |
|||
division32R: |
|||
push {r3-r9,lr} @ save registers |
|||
mov r6,#0 @ init upper upper part remainder !! |
|||
mov r7,r1 @ init upper part remainder with upper part dividende |
|||
mov r8,r0 @ init lower part remainder with lower part dividende |
|||
mov r9,#0 @ upper part quotient |
|||
mov r4,#0 @ lower part quotient |
|||
mov r5,#32 @ bits number |
|||
1: @ begin loop |
|||
lsl r6,#1 @ shift upper upper part remainder |
|||
lsls r7,#1 @ shift upper part remainder |
|||
orrcs r6,#1 |
|||
lsls r8,#1 @ shift lower part remainder |
|||
orrcs r7,#1 |
|||
lsls r4,#1 @ shift lower part quotient |
|||
lsl r9,#1 @ shift upper part quotient |
|||
orrcs r9,#1 |
|||
@ divisor sustract upper part remainder |
|||
subs r7,r2 |
|||
sbcs r6,#0 @ and substract carry |
|||
bmi 2f @ négative ? |
|||
@ positive or equal |
|||
orr r4,#1 @ 1 -> right bit quotient |
|||
b 3f |
|||
2: @ negative |
|||
orr r4,#0 @ 0 -> right bit quotient |
|||
adds r7,r2 @ and restaur remainder |
|||
adc r6,#0 |
|||
3: |
|||
subs r5,#1 @ decrement bit size |
|||
bgt 1b @ end ? |
|||
mov r0,r4 @ lower part quotient |
|||
mov r1,r9 @ upper part quotient |
|||
mov r2,r7 @ remainder |
|||
100: @ function end |
|||
pop {r3-r9,lr} @ restaur registers |
|||
bx lr |
|||
/***************************************************/ |
|||
/* ROUTINES INCLUDE */ |
|||
/***************************************************/ |
|||
.include "../affichage.inc" |
|||
</lang> |
|||
<pre> |
|||
959861 |
|||
333139 |
|||
981593 |
|||
524817 |
|||
432883 |
|||
</pre> |
|||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
<lang AWK> |
<lang AWK> |
Revision as of 16:08, 6 April 2022
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.
Ada
<lang Ada>with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
type long is range 0 .. 2**64; Seed : long := 675_248; function random return long is begin Seed := Seed * Seed / 1_000 rem 1_000_000; return Seed; end random;
begin
for I in 1 .. 5 loop Put (long'Image (random)); end loop; New_Line;
end Main;</lang>
- Output:
959861 333139 981593 524817 432883
ALGOL 68
Uses (long) integers. <lang algol68>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</lang>
- Output:
959861 333139 981593 524817 432883
AppleScript
<lang applescript>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</lang>
- Output:
<lang applescript>{959861, 333139, 981593, 524817, 432883}</lang>
ARM Assembly
<lang ARM Assembly> /* ARM assembly Raspberry PI or android with termux */ /* program pRandom.s */
/* REMARK 1 : this program use routines in a include file see task Include a file language arm assembly for the routine affichageMess conversion10 see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */ /************************************/ /* Constantes */ /************************************/ .include "../constantes.inc"
/*********************************/ /* Initialized data */ /*********************************/ .data sMessResult: .asciz " @ \n" szCarriageReturn: .asciz "\n"
iSeed: .int 675248 /*********************************/ /* UnInitialized data */ /*********************************/ .bss sZoneConv: .skip 24 /*********************************/ /* code section */ /*********************************/ .text .global main main: @ entry of program
ldr r0,iAdriSeed ldr r3,[r0] mov r2,#5
1:
mov r0,r3 bl computePseudo mov r3,r0 ldr r1,iAdrsZoneConv bl conversion10 @ call décimal conversion ldr r0,iAdrsMessResult ldr r1,iAdrsZoneConv @ insert conversion in message bl strInsertAtCharInc bl affichageMess @ display message subs r2,r2,#1 bgt 1b
100: @ standard end of the program
mov r0, #0 @ return code mov r7, #EXIT @ request to exit program svc #0 @ perform the system call
iAdrszCarriageReturn: .int szCarriageReturn iAdrsMessResult: .int sMessResult iAdrsZoneConv: .int sZoneConv iAdriSeed: .int iSeed /***************************************************/ /* compute pseudo random number */ /***************************************************/ /* r0 contains the number */ computePseudo:
push {r1-r2,lr} @ save registers mov r2,r0 umull r0,r1,r2,r2 ldr r2,idiv bl division32R ldr r2,idiv2 bl division32R mov r0,r2 pop {r1-r2,pc} @ restaur registers
idiv: .int 1000 idiv2: .int 1000000 /***************************************************/ /* division number 64 bits in 2 registers by number 32 bits */ /***************************************************/ /* r0 contains lower part dividende */ /* r1 contains upper part dividende */ /* r2 contains divisor */ /* r0 return lower part quotient */ /* r1 return upper part quotient */ /* r2 return remainder */ division32R:
push {r3-r9,lr} @ save registers mov r6,#0 @ init upper upper part remainder !! mov r7,r1 @ init upper part remainder with upper part dividende mov r8,r0 @ init lower part remainder with lower part dividende mov r9,#0 @ upper part quotient mov r4,#0 @ lower part quotient mov r5,#32 @ bits number
1: @ begin loop
lsl r6,#1 @ shift upper upper part remainder lsls r7,#1 @ shift upper part remainder orrcs r6,#1 lsls r8,#1 @ shift lower part remainder orrcs r7,#1 lsls r4,#1 @ shift lower part quotient lsl r9,#1 @ shift upper part quotient orrcs r9,#1 @ divisor sustract upper part remainder subs r7,r2 sbcs r6,#0 @ and substract carry bmi 2f @ négative ? @ positive or equal orr r4,#1 @ 1 -> right bit quotient b 3f
2: @ negative
orr r4,#0 @ 0 -> right bit quotient adds r7,r2 @ and restaur remainder adc r6,#0
3:
subs r5,#1 @ decrement bit size bgt 1b @ end ? mov r0,r4 @ lower part quotient mov r1,r9 @ upper part quotient mov r2,r7 @ remainder
100: @ function end
pop {r3-r9,lr} @ restaur registers bx lr
/***************************************************/ /* ROUTINES INCLUDE */ /***************************************************/ .include "../affichage.inc" </lang>
959861 333139 981593 524817 432883
AWK
<lang AWK>
- 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)
} </lang>
- Output:
1: 959861 2: 333139 3: 981593 4: 524817 5: 432883
C
<lang c>#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;
}</lang>
- Output:
959861 333139 981593 524817 432883
C++
<lang cpp>#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;
}</lang>
- Output:
959861 333139 981593 524817 432883
CLU
<lang clu>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</lang>
- Output:
959861 333139 981593 524817 432883
COBOL
<lang cobol> 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.</lang>
- Output:
959861 333139 981593 524817 432883
F#
<lang fsharp> // 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") </lang>
- Output:
959861 333139 981593 524817 432883
Factor
<lang factor>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</lang>
- Output:
959861 333139 981593 524817 432883
Forth
The loop keeps the seed on top of the stack. <lang forth>: next-random dup * 1000 / 1000000 mod ;
- 5-random-num 5 0 do next-random dup . loop ;
675248 5-random-num</lang>
- Output:
959861 333139 981593 524817 432883 ok
FreeBASIC
<lang freebasic>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 </lang>
Go
<lang go>package main
import "fmt"
func random(seed int) int {
return seed * seed / 1e3 % 1e6
}
func main() {
seed := 675248 for i := 1; i <= 5; i++ { seed = random(seed) fmt.Println(seed) }
}</lang>
- Output:
959861 333139 981593 524817 432883
Haskell
<lang haskell>findPseudoRandom :: Int -> Int findPseudoRandom seed =
let square = seed * seed squarestr = show square enlarged = replicate ( 12 - length squarestr ) '0' ++ squarestr in read $ take 6 $ drop 3 enlarged
solution :: [Int] solution = tail $ take 6 $ iterate findPseudoRandom 675248</lang>
- Output:
[959861,333139,981593,524817,432883]
J
<lang j>(_6{._3}.])&.:(10&#.^:_1)@(*~) ^: (>:i.6) 675248</lang>
- Output:
959861 333139 981593 524817 432883 387691
jq
Works with gojq, the Go implementation of jq
The proposed PRNG hardly deserves the name and so this entry avoids it. <lang jq># 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)</lang>
- Output:
As expected.
Julia
<lang julia>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
</lang>
- Output:
959861 333139 981593 524817 432883
Nim
<lang nim>proc rand:int =
var seed {.global.} = 675248 seed = int(seed*seed) div 1000 mod 1000000 return seed
for _ in 1..5: echo rand()</lang>
- Output:
959861 333139 981593 524817 432883
Perl
<lang perl>#!/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;</lang>
- Output:
959861 333139 981593 524817 432883
Phix
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
<lang PureBasic>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</lang>
- Output:
1: 959861 2: 333139 3: 981593 4: 524817 5: 432883
Python
<lang python>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())
</lang>
- Output:
959861 333139 981593 524817 432883
Raku
<lang perl6>sub msq {
state $seed = 675248; $seed = $seed² div 1000 mod 1000000;
}
say msq() xx 5;</lang>
- Output:
(959861 333139 981593 524817 432883)
Red
<lang rebol>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]</lang>
- Output:
959861 333139 981593 524817 432883
Ruby
<lang ruby>def middle_square (seed)
return to_enum(__method__, seed) unless block_given? s = seed.digits.size loop { yield seed = (seed*seed).to_s.rjust(s*2, "0")[s/2, s].to_i }
end
puts middle_square(675248).take(5)</lang>
- Output:
959861 333139 981593 524817 432883
Sidef
<lang ruby>class MiddleSquareMethod(seed, k = 1000) {
method next { seed = (seed**2 // k % k**2) }
}
var obj = MiddleSquareMethod(675248) say 5.of { obj.next }</lang>
- Output:
[959861, 333139, 981593, 524817, 432883]
UNIX Shell
<lang bash>seed=675248 random(){
seed=`expr $seed \* $seed / 1000 % 1000000` return seed
} for ((i=1;i<=5;i++)); do
random echo $?
done</lang>
- Output:
The same as Python's
VBA
- See Visual Basic
Visual Basic
<lang vb>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</lang>
- Output:
As expected.
Wren
<lang ecmascript>var random = Fn.new { |seed| ((seed * seed)/1e3).floor % 1e6 }
var seed = 675248 for (i in 1..5) System.print(seed = random.call(seed))</lang>
- Output:
959861 333139 981593 524817 432883
XPL0
<lang XPL0>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, ^ )];
]</lang>
- Output:
959861 333139 981593 524817 432883