3

currently I'm working with

double fRand(double fMin, double fMax)
{
    double f = (double)rand() / RAND_MAX;
    return fMin + f * (fMax - fMin);
}

double RangeFinder::getRange(void) {
  return fRand(0, 1700);
};


char range[12];
double r = rangeFinder.getRange();
snprintf(range, 11, "range: %d", r);

But it isn't giving me between 0,1700 its giving me between -99,999 ( I think ). I have a feeling the msb is interpretting the thousands place as negative.

What's the fix?


Edit

fixed version

double fRand(double fMin, double fMax)
{
    double f = (double)rand() / RAND_MAX;
    return fMin + f * (fMax - fMin);
}

double RangeFinder::getRange(void) {
  return fRand(0, 1700);
};



char range[22];
int r = rangeFinder.getRange();
snprintf(range, 22, "range: %i    ", r);
LCDString(range);

the 2nd arg to snprintf was 11.. too short. there weren't white characters after the number to clear out previous values, and the double r needed to be cast int r.

Community
  • 1
  • 1
dansch
  • 6,059
  • 4
  • 43
  • 59
  • Keep running it. *Sure* it is in the reported [-99,999] range? I doubt it. Trivially, with reduction of the supplied values: `return f * 1700`, where `0.0 <= f <= 1.0` due to `(double)rand()/RAND_MAX`. – user2864740 Feb 12 '14 at 21:00
  • 1
    Consider that `%d` is questionable in this case, as `r` is typed as a `double`. Try to cast `r` while supplying it to `snprintf`, use a different format specifier, and/or return `int` from getRange. – user2864740 Feb 12 '14 at 21:07
  • @ShafikYaghmour: No, it's not a duplicate of that question. The OP's logic in `fRand` is correct; the problem is the use of a `"%d"` format string for a `double` argument. – Keith Thompson Feb 12 '14 at 21:10
  • @user2864740 you were right. Just using `%f` or `%lf` in the string gave me `?` instead of a number, but casting it as `int` instead of `double` and changing `%d` to `%i` worked. Also, i had to add spaces afterwards to clear out the numbers staying on the lcd – dansch Feb 12 '14 at 21:30
  • See second answer here: http://stackoverflow.com/questions/686353/c-random-float-number-generation. Note that it is now part of standard library. – n0rd Feb 12 '14 at 21:46
  • i can't use standard lib as this is going to a microcontroller atmega – dansch Feb 20 '14 at 20:49

2 Answers2

5

A possible problem is that the "%d" is used for integers. In order to print float/doubles you should use "%f"(floats) or "%lf"(doubles or long float).

Simon Soriano
  • 803
  • 12
  • 19
  • 1
    Yes, that's the problem. Except that `"%f"` is for both `float` and `double` (because `float` arguments are promoted to `double` for variadic functions), and `"%Lf"` is for `long double`. `"%lf"` is equivalent to `"%f"`. (There is no `long float`.) – Keith Thompson Feb 12 '14 at 21:09
3

A word of caution: Stephan T. Lavavej, in his presentation rand() Considered Harmful, made a strong point on why not to use rand() in C++ and showcased the c++11 alternatives.

Your fRand could be written as

#include <random>

double fRand(double fMin, double fMax)
{
    std::random_device rd;

    std::mt19937 e2(rd());
    std::uniform_real_distribution<> dist(fMin, fMax);

    return dist(e2);
}

The additional gain here (besides using a robust and correct proven piece of code) is that

  1. std::uniform_real_distribution produces random floating-point values i, uniformly distributed on the interval [fMin, fMax), so you won't be introducing any bias in your randomness.

  2. Your are producing directly random floating-point values and not integers which are then cast to double.

Nikos Athanasiou
  • 29,616
  • 15
  • 87
  • 153
  • well thanks for the insight, but in production, the random data will be real data, so I'm not too worried about it. – dansch Feb 12 '14 at 21:50
  • Also be sure to truncute your floating point number inside the sprintf as so "%.nlf" where n is the number of digits you want to use and the size of the char array, or else you're overflow it – Nikos Athanasiou Feb 12 '14 at 21:56
  • Also use [sprintf_s](http://msdn.microsoft.com/en-us/library/ce3zzk1k.aspx) as sprintf is not safe (modern compilers will complain about its usage) – Nikos Athanasiou Feb 12 '14 at 21:57