Random number
This is an open discussion with 18 replies, filed under General.
Search
libXSLT supports math:random()
: http://exslt.org/math/functions/random/math.random.html. Just initialize your stylesheet with the following:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://exslt.org/math" extension-element-prefixes="math">
then use the method similar to
<xsl:value-of select="math:random()" />
The only downside to math:random()
is that it will only produce a number between 0 and 1. But you're all smart monkeys, I'm sure you can multiply it by 100 or some nonsense.
Isn't that how most random number generators work? How is it a downside?
Thank you guys. This is great. I'm implementing this jQuery and CSS3 gallery
Bumping this old thread instead of starting a new one,
Is there any way to specify a range of numbers? Like if i'd want 1, 2 or 3 as a result?
Is there any way to specify a range of numbers? Like if i'd want 1, 2 or 3 as a result?
Not with math:random()
, it only returns a random number from 0 to 1. A simple custom event is your best bet, something like:
<?php
require_once(TOOLKIT . '/class.event.php'); Class eventrandom_number extends Event { public $dsParamROOTELEMENT = 'random-number'; public static function about() { return array( 'name' => 'Random Number', 'author' => array( 'name' => 'Your Name', 'website' => 'Your Website', 'email' => 'Your Email'), 'version' => 'Symphony 2.2.5', 'release-date' => '2012-03-08' ); } public function load() { return $this->__trigger(); } public static function documentation() { return new XMLElement('p', 'Chooses a random number.'); } protected function __trigger() { $result = new XMLElement($this->dsParamROOTELEMENT); $result->setAttribute('number', rand(5,20)); return $result; } } ?>
Change the range for rand()
to what you want. Put it in your events
folder and name it event.random_number.php
.
Not easily. But you you just want 1, 2 or 3, and the random number is between 0 and 1, you can test the random number. If it's less than 0.3333... then return 1, less than 0.6666... return 2, or above return 3. Change the fraction depending on the range. You could write this as a choose/when statement.
Creative Nick!
Very easily.
<xsl:value-of select="floor(math:random()*3) + 1"/>
math:random()*3
generates a random number between 0 and 3, floor()
rounds down to the next integer (0,1,2,3) and +1
offsets the whole set to (1,2,3,4).
But since the probability of math:random()
picking 1.0
approaches zero the whole set shrinks to (1,2,3).
@phoque if you can't come back with an elegant algorithm in XSLT to solve this, you should declare your life a failure.
Updated my post. :-D
I hope I'm correct though... The implementors page is missing the important info about if 1.0
is actually never picked.
It does work mathematically but it comes down to the precision of the algorithm.
Bravo.
Nice @phoque, I'm going back to my corner now.
Oh, internally libxslt
is using
rand() / RAND_MAX;
wich divides the returnvalue of rand()
(a big integer) by its maximum possible value (depends on your system but for example 2147483647 = 231-1 on most Linux systems). This means that by a chance of 1 / 231-1 the above code will generate a random number outside the allowed range.
The fix is easy though: Modulo it by the allowed maximum number
<xsl:value-of select="(floor(math:random()*3) + 1) mod 4"/>
It only skews the distribution a bit (getting 1
is now 1 / 231-1 more likely) but solves the range issue.
Thanks four your input!
Doing a switch for math:rand() crossed my mind but it felt somewhat wild..
Phoques technique worked great, so i'm saving my event virginity a little bit more :)
@phoque: That is brilliant.
Modulo it by the allowed maximum number
With mod 4
you can still get 0
as result when the first operand is 4
(4 mod 4 = 0
), thus shifting the problem from an edge number to another one.
Solution:
(floor(math:random()*3) mod 3) + 1
In this case math:random()*3
ranges from 0
to 3
, with 3
being almost unlikely: the trick is to strip it out of the allowed values and then shift the result set ({0, 1, 2}
) by one position to the right. This is done respectively by mod 3
and + 1
.
Hah, you're right. Obviously the modulo has to be done before adding the offset.
Create an account or sign in to comment.
Is there a way to generate a random number in my xslt code? I've found this link but I'm not sure if the php parser will include the math extension.
Math Extension