Skip to content

Commit

Permalink
Add rand and randf functions for generating random numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed May 12, 2013
1 parent a14adc4 commit 167cc95
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 1 deletion.
16 changes: 16 additions & 0 deletions resources/function_help/rand-en_US
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<h3>rand() function</h3>
Returns a random integer within the range specified by the minimum and
maximum argument (inclusive).
<br>
This function takes two arguments.
<h4>Syntax</h4>
<code>rand(min, max)</code><br>

<h4>Arguments</h4>
<code>min</code> - an integer representing the smallest possible random number desired.<br>
<code>max</code> - an integer representing the largest possible random number desired.
<br>

<h4>Example</h4>
<!-- Show example of function.-->
<code>rand(1, 10) &rarr; 8</code><br>
16 changes: 16 additions & 0 deletions resources/function_help/randf-en_US
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<h3>rand() function</h3>
Returns a random float within the range specified by the minimum and
maximum argument (inclusive).
<br>
This function takes two arguments.
<h4>Syntax</h4>
<code>randf(min, max)</code><br>

<h4>Arguments</h4>
<code>min</code> - a float representing the smallest possible random number desired.<br>
<code>max</code> - a float representing the largest possible random number desired.
<br>

<h4>Example</h4>
<!-- Show example of function.-->
<code>randf(1, 10) &rarr; 4.59258286403147</code><br>
3 changes: 3 additions & 0 deletions src/app/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ int main( int argc, char *argv[] )
SetUnhandledExceptionFilter( qgisCrashDump );
#endif

// initialize random number seed
srand( time( NULL ) );

/////////////////////////////////////////////////////////////////
// Command line options 'behaviour' flag setup
////////////////////////////////////////////////////////////////
Expand Down
25 changes: 24 additions & 1 deletion src/core/qgsexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,27 @@ static QVariant fcnLog( const QVariantList& values, QgsFeature* , QgsExpression*
return QVariant();
return QVariant( log( x ) / log( b ) );
}
static QVariant fcnRndF( const QVariantList& values, QgsFeature* , QgsExpression* parent )
{
double min = getDoubleValue( values.at( 0 ), parent );
double max = getDoubleValue( values.at( 1 ), parent );
if ( max < min )
return QVariant();

// Return a random double in the range [min, max] (inclusive)
double f = ( double )rand() / RAND_MAX;
return QVariant( min + f * ( max - min ) ) ;
}
static QVariant fcnRnd( const QVariantList& values, QgsFeature* , QgsExpression* parent )
{
int min = getIntValue( values.at( 0 ), parent );
int max = getIntValue( values.at( 1 ), parent );
if ( max < min )
return QVariant();

// Return a random integer in the range [min, max] (inclusive)
return QVariant( min + ( rand() % ( int )( max - min + 1 ) ) );
}
static QVariant fcnToInt( const QVariantList& values, QgsFeature* , QgsExpression* parent )
{
return QVariant( getIntValue( values.at( 0 ), parent ) );
Expand Down Expand Up @@ -1207,7 +1228,7 @@ const QStringList &QgsExpression::BuiltinFunctions()
<< "sqrt" << "cos" << "sin" << "tan"
<< "asin" << "acos" << "atan" << "atan2"
<< "exp" << "ln" << "log10" << "log"
<< "round" << "toint" << "toreal" << "tostring"
<< "round" << "rand" << "randf" << "toint" << "toreal" << "tostring"
<< "todatetime" << "todate" << "totime" << "tointerval"
<< "coalesce" << "regexp_match" << "$now" << "age" << "year"
<< "month" << "week" << "day" << "hour"
Expand Down Expand Up @@ -1246,6 +1267,8 @@ const QList<QgsExpression::Function*> &QgsExpression::Functions()
<< new StaticFunction( "log10", 1, fcnLog10, QObject::tr( "Math" ) )
<< new StaticFunction( "log", 2, fcnLog, QObject::tr( "Math" ) )
<< new StaticFunction( "round", -1, fcnRound, QObject::tr( "Math" ) )
<< new StaticFunction( "rand", 2, fcnRnd, QObject::tr( "Math" ) )
<< new StaticFunction( "randf", 2, fcnRndF, QObject::tr( "Math" ) )
<< new StaticFunction( "$pi", 0, fcnPi, QObject::tr( "Math" ) )
<< new StaticFunction( "toint", 1, fcnToInt, QObject::tr( "Conversions" ) )
<< new StaticFunction( "toreal", 1, fcnToReal, QObject::tr( "Conversions" ) )
Expand Down
34 changes: 34 additions & 0 deletions tests/src/core/testqgsexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,40 @@ class TestQgsExpression: public QObject
QCOMPARE( v.toInt(), 200 );
}

void eval_rand()
{
QgsExpression exp1( "rand(1,10)" );
QVariant v1 = exp1.evaluate();
QCOMPARE( v1.toInt() <= 10, true );
QCOMPARE( v1.toInt() >= 1, true );

QgsExpression exp2( "rand(-5,-5)" );
QVariant v2 = exp2.evaluate();
QCOMPARE( v2.toInt(), -5 );

// Invalid expression since max<min
QgsExpression exp3( "rand(10,1)" );
QVariant v3 = exp3.evaluate();
QCOMPARE( v3.type(), QVariant::Invalid );
}

void eval_randf()
{
QgsExpression exp1( "randf(1.5,9.5)" );
QVariant v1 = exp1.evaluate();
QCOMPARE( v1.toDouble() <= 9.5, true );
QCOMPARE( v1.toDouble() >= 1.5, true );

QgsExpression exp2( "randf(-0.0005,-0.0005)" );
QVariant v2 = exp2.evaluate();
QCOMPARE( v2.toDouble(), -0.0005 );

// Invalid expression since max<min
QgsExpression exp3( "randf(9.3333,1.784)" );
QVariant v3 = exp3.evaluate();
QCOMPARE( v3.type(), QVariant::Invalid );
}

void referenced_columns()
{
QSet<QString> expectedCols;
Expand Down

0 comments on commit 167cc95

Please sign in to comment.