Dart Random number in a range

eye-catch Dart and Flutter

Dart language offers Random class to generate a random result of boolean, int, and double value. The usage is very simple. Let’s have a look.

Sponsored links

Basic usage of Random

Random class has 3 methods.

nextBool();
nextInt(int max);
nextDouble();   

Just call one of them after instantiating an instance.

final random = new Random();
for (var i = 0; i < loopCount; i++) {
  final boolValue = random.nextBool();
  final intValue = random.nextInt(100);
  final doubleValue = random.nextDouble();
  print("$boolValue\t$intValue\t$doubleValue");
}
// Bool    Int     Double
// ----------------------------------------
// false   47      0.8030808978673076
// false   2       0.3018160608691639
// true    45      0.9991493833440004
// false   88      0.414774595519641
// false   99      0.23824450531447028
// true    33      0.29656709090965194
// false   85      0.9747426076875625
// false   5       0.44814308497889466
// false   35      0.7952298650841252
// false   1       0.6126148790736863

The constructor has an optional argument called seed. If we pass an int number here, it always generates the same set of results. See the following example. The new instance is created in the for a loop. The result is always the same.

for (var i = 0; i < loopCount; i++) {
  print(Random(2).nextInt(100));
}
// 73
// 73
// 73
// 73
// 73
// 73
// 73
// 73
// 73
// 73

Be careful if you want to give a seed.

Sponsored links

Generate random value for Cryptography

If you want to generate random value for Cryptography, a normal constructor shouldn’t be used. It offers a different constructor Random.secure(). To generate a random value, it must be random, unpredictable, and irreproducible. If the seed can be predictable, the value can also be predictable.

Check the specification of the random generator if you need to generate it for Cryptography.

final secure = Random.secure();
for (var i = 0; i < loopCount; i++) {
  print(secure.nextInt(100));
}
// 6
// 26
// 45
// 55
// 45
// 89
// 51
// 66
// 0
// 80

Random int number in range

If we need to generate random values in a range, we need to add small logic. It looks like this.

final min = 30;
final max = 100;
for (var i = 0; i < loopCount; i++) {
  print(min + random.nextInt(max - min));
}

In this case above, max – min is 70. Therefore, random.nextInt(70); can be 0 – 70. We want at least 30, its min value needs to be added.

Random double number in range

I tried some ways. Come to the point, this way is the simplest.

double _generateDouble2(double minValue, double maxValue, int precision) {
  final random = new Random();
  final doubleRandom = minValue + (maxValue - minValue) * random.nextDouble();
  return double.parse(doubleRandom.toStringAsFixed(precision));
}

for (var i = 0; i < loopCount; i++) {
  final value = _generateDouble2(4.1, 10.432, 4);
  print("$value");
}
// 6.6825
// 7.683
// 10.016
// 6.3594
// 4.4341
// 4.5369
// 6.4781
// 8.2649
// 7.8907
// 4.2494

Basically, it’s the same logic as the int version. nextDouble doesn’t have any arguments, we have to add the logic there. I used the combination of double.parse and toStringAsFixed to get a precise number. If we want to have 3 digits after the decimal point, we somehow need to cut the rest.

The first way that I tried to get a random double number in the range 0 – 10 with 2 digits after the decimal point is as follows.

for (var i = 0; i < loopCount; i++) {
  print(random.nextInt(1000) * 0.01);
}
// 9.84
// 5.47
// 1.56
// 8.97
// 0.8
// 9.450000000000001
// 1.19
// 7.8
// 0.42
// 3.2800000000000002

The value sometimes gets crazy because of the way of calculation.

The next way is as follows but it can’t control the value after the decimal point.

for (var i = 0; i < loopCount; i++) {
  double value = random.nextDouble() * 10;
  value = double.parse(value.toStringAsFixed(2));
  print(value);
}
// 8.83
// 9.0
// 3.2
// 0.37
// 9.55
// 4.46
// 5.1
// 9.16
// 8.13
// 6.11

The last way is tricky. No one wants to apply this logic.

double _generateDouble(double minValue, double maxValue, int precision) {
  final minValues = minValue.toString().split(".");
  final maxValues = maxValue.toString().split(".");

  final maxLengthAfterDecimalPoint = max(
    minValues[1].length,
    maxValues[1].length,
  );

  // e.g. min 5.51, max 11.234
  // -->  5510    , 11234
  final intMin = minValue * pow(10, maxLengthAfterDecimalPoint);
  final intMax = maxValue * pow(10, maxLengthAfterDecimalPoint);

  final random = new Random();
  final intRandom =
      intMin.toInt() + random.nextInt(intMax.toInt() - intMin.toInt());

  final doubleRandom = intRandom * pow(0.1, maxLengthAfterDecimalPoint);
  return double.parse(doubleRandom.toStringAsFixed(precision));
}

for (var i = 0; i < loopCount + 40; i++) {
  final value = _generateDouble(5.51, 11.234, 3);
    print("$value");
}
// 7.488
// 7.968
// 9.73
// 7.836
// 9.543
// 8.483
// 6.805
// 7.607
// 10.991
// 8.222

Comments

Copied title and URL