## Re: [xsl] Random number generator that returns numbers from a normal probability distribution and with a specified standard deviation?

 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" 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 &lt; \$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 ()

```