Can you get truly random numbers from Dynamics NAV?

josephdewey
Member Posts: 87
I use random numbers for testing a lot, and I'm used to Excel, where you can get a lot of precision from '=RAND()'
It seems like the easiest way to replicate the Excel RAND function in Navision is with this code:
Is there something better in Navision than RANDOM? Or, do you know if future versions of Navision will support random numbers that are more random?
It seems like the easiest way to replicate the Excel RAND function in Navision is with this code:
RANDOMIZE; x := RANDOM(2147483647)/2147483647)And, then this really isn't a true random number, but it's based on an algorithm that wouldn't pass really advanced randomness tests.
Is there something better in Navision than RANDOM? Or, do you know if future versions of Navision will support random numbers that are more random?
Joseph Dewey
Microsoft Dynamics NAV User
Microsoft Dynamics NAV User
0
Comments
-
Hope this helps
:-
RandomDigit := CREATEGUID;
RandomDigit := DELCHR(RandomDigit,'=','{}-01');
RandomDigit := COPYSTR(RandomDigit,1,10);0 -
Well, also GUID is not really random, but it probably is more random than RANDOM.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
take the last digit of currentdatetime, (the ones after the decimal seperator).
Guaranteed to be random.0 -
or also with TIME.
I tried this code:for i := 1 to 1000000 do begin tim := time; tim2 := 000000T; int := (tim - tim2) MOD 1000; tmpInteger.Number := int; if tmpInteger.insert then ; end; message('%1',tmpInteger.count);
With this I wanted to see if the last 2 digits (the milliseconds) can have all values and the count is always close to 1000. So this is not a bad system.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
Using the last digit of the thousands in TIME (the milliseconds count) to generate a random number is definitely a unique approach. The biggest problem with this, though, is that Navision does many calculations per millisecond, so even though this would probably generate a random enough number between 0 and 9, then it kind of falls apart when you need something outside of the 0 to 9 range, or if you need multiple numbers.
But, I did make a working prototype that gives pretty random numbers. It's pretty slow, and I would guess that it wouldn't pass too many heavy-duty randomness tests. Also, about half of the time this gives a number with far fewer decimal places than the max. I don't understand why my code does that.
But the numbers it generates do look random.FOR j := 1 TO 10 DO BEGIN rand_string := '0.'; FOR i := 1 TO 20 DO BEGIN rand_string := rand_string + COPYSTR(FORMAT(TIME,0,'<Thousands>'),3,1); SLEEP(1); //try removing this to see what happens END; EVALUATE(rand_dec, rand_string); MESSAGE('%1',rand_dec); END;
Thanks for your ideas!Joseph Dewey
Microsoft Dynamics NAV User0 -
Were do you need to use such a generator?
I guess you could use some dll file that does only than, or even use Excel automation to generate a random number...0 -
Here's my code for using the CREATEGUID to get a random number between 0 and 1.
FOR j := 1 TO 10 DO BEGIN rand_string := '0.'; WHILE STRLEN(rand_string) < 20 DO rand_string := rand_string + DELCHR(CREATEGUID,'=','{}-ABCDEF'); EVALUATE(rand_dec, rand_string); MESSAGE('%1',rand_dec); END;
I think this is going to be the best method, if I want a true random number, but I think I'll probably mostly just use Navision's RANDOM function. It did pass a few randomness tests that I threw at it.
I use random numbers for testing, mostly. But random numbers are very helpful in a lot of situations. How would I learn how to hook Navision up to a DLL or Excel's automation?Joseph Dewey
Microsoft Dynamics NAV User0 -
It depends on the version you are using.
You can look at the Excel Buffer Table to see how to Interact with excel. Otherwise you could create a .NET dll or COM interface depending on the version.0 -
kapamarou wrote:You can look at the Excel Buffer Table to see how to Interact with excel. Otherwise you could create a .NET dll or COM interface depending on the version.
-you need Excel installed (and probably it must be the correct version)
-It is probably slower than RANDOM because you have to connect to .NET or COM.
After all, why do you need a random no. in NAV. Only to do some tests and for that the C/AL RANDOM is good enough.
If you need random numbers in a scientific way, you
1) need some black box (don't remember the name) that generates really random numbers using quantum fluctuations (some companies have created such a thing)
2) you're really using the wrong language/development environment for that.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
All in all, I think the topic is answered.
However, I am very curious in what business process a random number is needed.
Is it like a random discount? If you're lucky you'll receive a 100% discount?0 -
If you want to delve into the science of randomness, then look at this site: http://www.random.org/randomness/No support using PM or e-mail - Please use this forum. BC TechDays 2024: 13 & 14 June 2024, Antwerp (Belgium)0
-
Schrodinger's cat is long dead anyway, so why does it matter.
Get a dog instead. 8)David Singleton0 -
David Singleton wrote:Schrodinger's cat is long dead anyway, so why does it matter.
(And how is this ontopic? I seem to have missed the link between Shrodingers cat and randomness)0 -
But if I open the box then the randomness is gone. My gut feeling is that after all these decades trapped in the box that the kitten has by now starved or suffocatedDavid Singleton0
-
Sog wrote:However, I am very curious in what business process a random number is needed.
Is it like a random discount? If you're lucky you'll receive a 100% discount?- Quality testing/random sample
- Pick a random customer for something like a survey
- Randomly pick items for inventory counts
- Unique identifier generation
And, I agree, RANDOM is usually good enough. But, NAV is an extensible ERP system after all. And NAV's a top tier product, also.
From the NAV documentation, RANDOM returns "A pseudo-random number." I guess the thing that bugs me most about it, is that this is a reminder than Dynamics NAV is built on top of a super old, creaky programming language. Pretty much all modern programming languages have the ability to generate real random numbers, and have gotten rid of the pseudo-random algorithms.Joseph Dewey
Microsoft Dynamics NAV User0 -
josephdewey wrote:Pretty much all modern programming languages have the ability to generate real random numbers, and have gotten rid of the pseudo-random algorithms.0
-
Well, after doing some research, it looks like I was wrong. Most modern programming languages all use similar algorithms behind the scenes.
There are only two differences, as far as I can see:
#1: Most modern programming languages have the RANDOMIZE command built in. For example, Java uses as a seed the number of milliseconds since January 1, 1970. So, you don't have to initialize random numbers with a RANDOMIZE command in other languages.
#2: In Navision, you get a random number in only 4% of the total possible set of random numbers 1 and 2,147,483,647, for your first random number. Here's the math. There are 24*60*60*1000 (86,400,000) milliseconds in a day, so this is the maximum number of possible seed values for the random number. So the most unique random numbers that will be returned are 86,400,000/2,147,483,647, or 4.02%.
Or, in other words, the following code will never return 96% of all possible numbers between 1 and 2147483647:RANDOMIZE(); MESSAGE('%1',RANDOM(2147483647));
But, the second time you run the second line, it should give equal chances of getting every number.
So, are Navision random numbers really random? I guess the answer really is: they're random enough.Joseph Dewey
Microsoft Dynamics NAV User0 -
josephdewey wrote:So, are Navision random numbers really random? I guess the answer really is: they're random enough.
Try to implement a simple Dice.randomize(); //with a seed it's the same problem message('The number is: %1 <- odd ?', random(6));
The first number is always an odd value (1, 3 or 5). :bug: :bug: :bug: :bug: :bug:
BTW: It's the same with all even values in the random function.
random(<even value>) returns an <odd value> at the first try.
Kind regards,
winfy0 -
Hi winfy,
Thanks very much! This is great, simple sample code. I tested it a bunch of times and I never got an even number. I'm curious how you found this random deficiency in NAV.Joseph Dewey
Microsoft Dynamics NAV User0 -
When trust is lost:
Park and Millers Minimal Standard Random Number Generator is simple, fast and in my opinion good enough for the most simulations in Navision.
Random2(VAR Seed : Integer;Number : Integer) : Integer//...................................................................................................... //Name: Minimal Standard Random Number Generator (linear congruential generator) //Source: Steve K. Park and Keith W. Miller "Random Number Generators: Good ones are hard to find", 1988 //Language: Navision C/AL (modified by winfy) //Limits: only 32 Bit signed Integer. Generates Numbers from 1 to Parameter "Number" //...................................................................................................... //Definitions //a,m,q,r (Type Integer) //test, hi, lo (Type Integer) //Seed (Typ Integer) //Initialize the "good" Values //the other Values are good alternatives too a:= 16807; //a:= 48271; //a:= 39373; m:= 2147483647; q:= 127773; //q:= 44488; //q:= 54542; r:= 2836; //r:= 3399 //r:= 1481; //Generate the Random Number hi := Seed DIV q; lo := Seed MOD q; test := a * lo - r * hi; //Change to a positive range IF test > 0 THEN Seed := test ELSE Seed := test + m; //Result between 1 and the Parameter Number IF (Number > 0) THEN EXIT((Seed MOD Number) + 1) ELSE EXIT(1); //alternative EXIT(0) or Errormessage
Someone post it here before.
I think it's good enough to generate a Startseed with it.
Randomize2(VAR Seed : Integer)//Generate a Seed with GUID values between 1 und 2.147.483.646. //bigseed (Type BigInteger) EVALUATE(bigseed, COPYSTR(DELCHR(CREATEGUID(),'=','{}-ABCDEF'),1,10)); Seed:= (bigseed MOD 2147483646) +1;
Maybe useful?
Literature: (Link)
Kind regards,
winfy0 -
Forgive me as this thread is ancient, but nobody seemed to mention anything about parallel execution. If a SOAP enabled codeunit function were to seed the Navision random generator and multiple (simultaneous enough) requests could generate the same seed since internally it's based on the millisecond counter and a millisecond is actually a HUGE unit of time. For an application like password reset this could be disastrous. A higher precision timer needs to be evaluated at instantiation, or ideally like kriki said a truly random source.
Nonetheless, here's my seeding solution, which is probably slow, but hopefully there's always enough schedule changes between multiple simultaneous calls to ensure different last loop times. I assume CREATEGUID uses a higher precision timer. I'll do testing with parallelism and post my findings.j, integer rand_string, text FOR j := 1 TO 100 DO BEGIN rand_string := rand_string + FORMAT(CREATEGUID); END; seed := ComputeHash(rand_string);
public static int ComputeHash(string subject) { using (var ha = new MD5CryptoServiceProvider()) { using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(subject))) { return BitConverter.ToInt32(ha.ComputeHash(ms), 0); } } }
0 -
Yep, I did ti 3 years before to generate tracking no and till now no issue.
What I wrote was something like that.
WHILE NOT UniqueValue DO BEGIN
"Tracking No":=GenerateTrackingNo;
IF NOT CheckDuplicateTracking("Tracking No") THEN
UniqueValue := TRUE;
END;
Where GenerateTrackingNo was the function which was generating unique number with Random NAV Keyword and CheckDuplicateTracking was the function where I was just cross validating that the generated tracking number doesn't exist in the Database.
P.S - Till 6 month it was OK but after then what I experienced was system had started generating duplicate tracking numbers hence added to cross verify with the existing one in the DB.Thanks
Blog - rockwithnav.wordpress.com/
Twitter - https://twitter.com/RockwithNav
Facebook - https://facebook.com/rockwithnav/0 -
The default method of seeding the PRNG is based on time so if several instances are all synchronized (they all began execution at the same exact moment) they will all have the same seed, and thus the same PRNG output (very bad). The CREATEGUID function and .NET's Guid.NewGuid might be doing something different or tap into a more precise timer, which shrinks that "exact moment" window, since people here are saying "it's probably more random"0
-
My test passed when exposing a codeunit that returns a CREATEGUID generated value via SOAP web service and running 1000 rounds of 8 simultaneous requests to the web service. every round had 8 distinct values. either there's some kind of blocking going on in the way Navision handles SOAP web requests or the time window CREATEGUID uses is small enough that it's safe to use CREATEGUID like this. I imagine we wouldn't have people suggesting its use if it weren't. If anyone has more insight into how Navision handles web requests it would be interesting to me. I'm going to run it overnight with 2 threads per round and I'm confident it will pass. Thanks!
static long y = 0; // threads finished count static long x = Environment.ProcessorCount * 1; // number of simultanious requests static ManualResetEvent done = new ManualResetEvent(false); // detect round finish static ManualResetEvent go = new ManualResetEvent(false); // synchronize request start times static ConcurrentBag<int> results = new ConcurrentBag<int>(); static Test2.test2 p = new Test2.test2(); // navision codeunit via SOAP web service private static void work(object r) { var ready = (ManualResetEvent)r; ready.Set(); go.WaitOne(); results.Add(p.GetRand2()); if (Interlocked.Increment(ref y) == x) done.Set(); } static void Main(string[] args) { p.Credentials = new NetworkCredential("***********", "**********"); for (int round = 0; round < 1000; round++) { for (int i = 0; i < x; i++) { ManualResetEvent ready = new ManualResetEvent(false); Thread g = new Thread(new ParameterizedThreadStart(work)); g.Start(ready); ready.WaitOne(); } go.Set(); done.WaitOne(); var p = results.Distinct(); if (p.Count() != results.Count) throw new Exception("Test: FAIL"); Console.Write('.'); go.Reset(); done.Reset(); y = 0; results = new ConcurrentBag<int>(); } Console.WriteLine("Test: PASS"); Console.ReadKey(); }
0 -
I think that you cannot physically have 8 sessions running concurrently. The requests come through a network card so requests are serialized one way or antoher - if not by your code then by the OS and by the hardware along the way. The time difference migh be quite significant - if your card works at 1Gbps sending single TCP packet takes time measured probably in microseconds.
If you run within the same machine while there is still a time required do copy the data between one process and another.Slawek Guzek
Dynamics NAV, MS SQL Server, Wherescape RED;
PRINCE2 Practitioner - License GR657010572SG
GDPR Certified Data Protection Officer - PECB License DPCDPO1025070-2018-030 -
Even serialized, if the requests all construct instances of a run-of-the-mill PRNG within the same window of time they will generate the same PRN sets. This depends on the granularity of the clock being used to seed the PRNG. .NET Random default constructor seeds itself with a 1 millisecond window, which is offensively huge and broken.
CREATEGUID is probably calling .NET Guid.NewGuid so I looked up Microsoft's explanation of what's happening under that hood.
Remarks
This is a convenient static method that you can call to get a new Guid. The method wraps a call to the Windows CoCreateGuid function. The returned Guid is guaranteed to not equal Guid.Empty.
Remarks
The CoCreateGuid function calls the RPC function UuidCreate, which creates a GUID, a globally unique 128-bit integer. Use CoCreateGuid when you need an absolutely unique number that you will use as a persistent identifier in a distributed environment.To a very high degree of certainty, this function returns a unique value – no other invocation, on the same or any other system (networked or not), should return the same value.
CREATEGUID is practically immune if it's using this, which is very good.0 -
A GUID is not perfectly unique. If you try to create a few 10^9 GUID's, you will hit some doubles.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!1
Categories
- All Categories
- 73 General
- 73 Announcements
- 66.6K Microsoft Dynamics NAV
- 18.7K NAV Three Tier
- 38.4K NAV/Navision Classic Client
- 3.6K Navision Attain
- 2.4K Navision Financials
- 116 Navision DOS
- 851 Navision e-Commerce
- 1K NAV Tips & Tricks
- 772 NAV Dutch speaking only
- 617 NAV Courses, Exams & Certification
- 2K Microsoft Dynamics-Other
- 1.5K Dynamics AX
- 320 Dynamics CRM
- 111 Dynamics GP
- 10 Dynamics SL
- 1.5K Other
- 990 SQL General
- 383 SQL Performance
- 34 SQL Tips & Tricks
- 35 Design Patterns (General & Best Practices)
- 1 Architectural Patterns
- 10 Design Patterns
- 5 Implementation Patterns
- 53 3rd Party Products, Services & Events
- 1.6K General
- 1.1K General Chat
- 1.6K Website
- 83 Testing
- 1.2K Download section
- 23 How Tos section
- 252 Feedback
- 12 NAV TechDays 2013 Sessions
- 13 NAV TechDays 2012 Sessions