Subject: Re: [xsl] Random number generator that returns numbers from a normal probability distribution and with a specified standard deviation? From: "Roger L Costello costello@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Fri, 5 Jun 2020 18:35:16 -0000 |
Thank you Mary for your XQuery implementation. I converted Mary's XQuery to XSLT. Below is my XSLT implementation of a random number generator that returns numbers in a normal distribution with a specified mean and specified standard deviation. /Roger ------------------------------------------------------- <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:random="random-number-generator-with-normal-distribution" xmlns:math="http://exslt.org/math" extension-element-prefixes="math" exclude-result-prefixes="#all" version="2.0"> <!-- Returns $length random numbers. The random numbers form a normal distribution (i.e., bell-shaped curve) and are centered around $mean with a standard deviation of $stddev. Algorithm used: the polar variant of the Box-Muller algorithm. Thanks to Mary Holstege for showing me how to implement this. --> <xsl:function name="random:sequence" as="xs:double*"> <xsl:param name="length" as="xs:integer" /> <xsl:param name="mean" as="xs:double" /> <xsl:param name="stddev" as="xs:double" /> <xsl:for-each select="1 to $length"> <xsl:sequence select="random:normal($mean, $stddev)" /> </xsl:for-each> </xsl:function> <xsl:function name="random:normal" as="xs:double"> <xsl:param name="mean" as="xs:double" /> <xsl:param name="stddev" as="xs:double" /> <xsl:sequence select="$mean + random:gauss() * $stddev" /> </xsl:function> <xsl:function name="random:gauss" as="xs:double"> <xsl:variable name="u" select="2 * math:random() - 1" as="xs:double" /> <xsl:variable name="v" select="2 * math:random() - 1" as="xs:double" /> <xsl:variable name="r" select="$u * $u + $v * $v" as="xs:double" /> <xsl:choose> <xsl:when test="($r = 0) or ($r >= 1)"> <xsl:sequence select="random:gauss()" /> </xsl:when> <xsl:otherwise> <xsl:variable name="c" select="math:sqrt(-2 * math:log($r) div $r)" as="xs:double" /> <xsl:sequence select="$u * $c" /> </xsl:otherwise> </xsl:choose> </xsl:function> <!-- ****************************** --> <!-- Test the above functions --> <!-- ****************************** --> <xsl:template match="/"> <!-- Get one million random numbers, normally distributed, with mean 0.5 and standard deviation 0.3 --> <xsl:variable name="random-numbers" as="xs:double*"> <xsl:sequence select="random:sequence(1000000, 0.5, 0.3)" /> </xsl:variable> <xsl:text>Percentage of the random numbers in the range: mean plus/minus one standard deviation = </xsl:text> <xsl:sequence select="count(for $j in $random-numbers return if (($j ge 0.2) and ($j le 0.8)) then $j else ()) div 1000000" /> <xsl:text> </xsl:text> <xsl:text>Percentage of the random numbers in the range: mean plus/minus two standard deviations = </xsl:text> <xsl:sequence select="count(for $j in $random-numbers return if (($j ge -0.1) and ($j le 1.1)) then $j else ()) div 1000000" /> <xsl:text> </xsl:text> <!-- Divide up the range 0 to 1 into 100 intervals and count the number of random numbers in each interval. --> <xsl:for-each select="1 to 100"> <xsl:variable name="i" select="." /> <xsl:variable name="lo" select="($i - 1) div 100" /> <xsl:variable name="hi" select="$i div 100" /> <xsl:sequence select="$i" /><xsl:text>. </xsl:text> <xsl:sequence select="count(for $j in $random-numbers return if (($j >= $lo) and ($j < $hi)) then $j else ())" /> <xsl:text> </xsl:text> </xsl:for-each> <!-- Show the random numbers --> <xsl:sequence select="$random-numbers" /> </xsl:template> </xsl:stylesheet> ------------------------------------------------------- From: Mary Holstege holstege@xxxxxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Sent: Tuesday, June 2, 2020 9:48 AM To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx Subject: [EXT] Re: [xsl] Random number generator that returns numbers from anormal probability distribution and with a specified standard deviation? I have an XQuery function that does it. It depends on an underlying function (here rand:uniform) to give uniform numbers in [0,1].B Most "random" functions will give you uniformly distributed random numbers; if your platform doesn't have one, you'll have to concoct your own pseudo-random function This is the polar variant of the Box-Muller algorithm (: : normal() : Return random normally distributed data. : : $mean: Mean of range of values : $std: Standard deviation of range of values :) declare function rand:normal( $mean as xs:double, $std as xs:double ) as xs:double { $mean + rand:gauss() * $std }; (: : gauss() : Return random normally distributed data between 0 and 1 : A service function used by normal() :) declare %private function rand:gauss() as xs:double { let $u as xs:double := 2 * rand:uniform(0,1) - 1 let $v as xs:double := 2 * rand:uniform(0,1) - 1 let $r := $u * $u + $v * $v return ( if ($r = 0 or $r >= 1) then rand:gauss() else ( let $c as xs:double := math:sqrt(-2 * math:log($r) div $r) return $u * $c ) ) }; On 5/31/20 10:37 AM, Roger L Costello mailto:costello@xxxxxxxxx wrote: Hi Folks, I need a random number generator that returns numbers from a normal probability distribution, centered around zero, and with standard deviation that can be specified. Has anyone created such a thing? I am using XSLT/XPath 2.0 /Roger http://www.mulberrytech.com/xsl/xsl-list http://lists.mulberrytech.com/unsub/xsl-list/673357 ()
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Random number generator t, Mary Holstege holste | Thread | [xsl] creating multi-level TOC from, Charlie0 charlieo0@x |
Re: [xsl] creating multi-level TOC , Martin Honnen martin | Date | [xsl] Stylesheet parameters and pac, David Birnbaum djbpi |
Month |