For-Loop in C++ Using Double Breaking Out One Step Early, Boundary Value Not Reached

For-loop in C++ using double breaking out one step early, boundary value not reached

When using floating point values not every value is exactly representable, 0.95+0.05 > 1 because 0.95 is not exactly representable by a double value.

See what Wikipedia has to say about floating point accuracy.

If you look at the IEEE floating point converter you'll see that the value of 0.95 in 64 bit floating point (double) is 0-01111111110-1110011001100110011001100110011001100110011001100110 by entering this in a floating point calculator you get the value is 0.95000016 and adding 0.05 to that takes you over the 1.0 mark.

This is why you should never use floating points in loops (or more generally compare the result of floating point calculation to an exact value).

Is floating point math broken?

Binary floating point math is like this. In most programming languages, it is based on the IEEE 754 standard. The crux of the problem is that numbers are represented in this format as a whole number times a power of two; rational numbers (such as 0.1, which is 1/10) whose denominator is not a power of two cannot be exactly represented.

For 0.1 in the standard binary64 format, the representation can be written exactly as

  • 0.1000000000000000055511151231257827021181583404541015625 in decimal, or
  • 0x1.999999999999ap-4 in C99 hexfloat notation.

In contrast, the rational number 0.1, which is 1/10, can be written exactly as

  • 0.1 in decimal, or
  • 0x1.99999999999999...p-4 in an analogue of C99 hexfloat notation, where the ... represents an unending sequence of 9's.

The constants 0.2 and 0.3 in your program will also be approximations to their true values. It happens that the closest double to 0.2 is larger than the rational number 0.2 but that the closest double to 0.3 is smaller than the rational number 0.3. The sum of 0.1 and 0.2 winds up being larger than the rational number 0.3 and hence disagreeing with the constant in your code.

A fairly comprehensive treatment of floating-point arithmetic issues is What Every Computer Scientist Should Know About Floating-Point Arithmetic. For an easier-to-digest explanation, see floating-point-gui.de.

Side Note: All positional (base-N) number systems share this problem with precision

Plain old decimal (base 10) numbers have the same issues, which is why numbers like 1/3 end up as 0.333333333...

You've just stumbled on a number (3/10) that happens to be easy to represent with the decimal system, but doesn't fit the binary system. It goes both ways (to some small degree) as well: 1/16 is an ugly number in decimal (0.0625), but in binary it looks as neat as a 10,000th does in decimal (0.0001)** - if we were in the habit of using a base-2 number system in our daily lives, you'd even look at that number and instinctively understand you could arrive there by halving something, halving it again, and again and again.

Of course, that's not exactly how floating-point numbers are stored in memory (they use a form of scientific notation). However, it does illustrate the point that binary floating-point precision errors tend to crop up because the "real world" numbers we are usually interested in working with are so often powers of ten - but only because we use a decimal number system day-to-day. This is also why we'll say things like 71% instead of "5 out of every 7" (71% is an approximation, since 5/7 can't be represented exactly with any decimal number).

So no: binary floating point numbers are not broken, they just happen to be as imperfect as every other base-N number system :)

Side Side Note: Working with Floats in Programming

In practice, this problem of precision means you need to use rounding functions to round your floating point numbers off to however many decimal places you're interested in before you display them.

You also need to replace equality tests with comparisons that allow some amount of tolerance, which means:

Do not do if (x == y) { ... }

Instead do if (abs(x - y) < myToleranceValue) { ... }.

where abs is the absolute value. myToleranceValue needs to be chosen for your particular application - and it will have a lot to do with how much "wiggle room" you are prepared to allow, and what the largest number you are going to be comparing may be (due to loss of precision issues). Beware of "epsilon" style constants in your language of choice. These can be used as tolerance values but their effectiveness depends on the magnitude (size) of the numbers you're working with, since calculations with large numbers may exceed the epsilon threshold.

increment of a for loop with a decimal value

Instead of:

for (double a = -0.2; a <= 0.2; a += 0.01)
{
...
}

use an integer loop index and calculate the corresponding floating point value within the loop, e.g.

for (int i = -20; i <= 20 ; ++i) // a = -0.2 to 0.2 step 0.01
{
const double a = i / 100.0;
...
}

In C - scanf() in a for loop is causing printf() to run multiple times

The problem with %c format specifier is that, it will read only one byte from the input buffer and if the input buffer has more in store and the call in encountered next time, it will not ask for user input, it will simply read the next byte from the available input stream.

So, to answer

How can I limit the length of their response?

well, there's no straightway approach that you can stop the user from entering only X characters/ digits, instead, swipe off the excess, (if any) and for the next call, start with an empty buffer is an easy approach.

So, the quick way out of this would be, to clean off the standard input of remaining inputs. You can do something like

  int retval = scanf(" %c", &play);

//some code

while (getchar() != '\n'); //eat up the input buffer

//next call to scanf(), input buffer is empty now....

to stop scanf() from reading already existing unwanted inputs and force it to ask the input from user.

Also, don't forget to check the return value of scanf() to ensure the success of the call.

Simple 'for' loop crashing program on final iteration

You need two changes. As stated in previous comments, your for ending condition should be < size-1 to prevent reading out of bounds. You also need to print the count of the last item, which will be wordCount because if it's unique wordCount is 1 and if not it has been already added. Corrected code:

for (int i = 0; i < size-1; i++) {
if (wordList[i] == wordList[i+1]) {
wordCount++;
}
else {
cout << wordList[i] << " " << wordCount << endl;
wordCount = 1;
}
}
cout << wordList[size-1] << " " << wordCount << endl;

simplifying nested for loop in C

Your num is simply iterating through all numbers from 0 (See Edit 2) to 999,999,999. So you really don't need to iterator over every digit. A simple way of doing what you want, even though probably not anymore efficient is this:

unsigned int num;
for (num = 0; num < 1000000000; ++num) // will take long
{
char digits[15];
unsigned int i, other_num;
sprintf(digits, "%09u", i); // division used here
other_num = 0;
for (j = 0; j < 9; ++j)
other_num += power(digits[j] - '0', len);
if (num == other_num)
printf(" %d ",num);
}

Note that you can do your power function in a more efficient way. See this question.


Edit 1: (Note: see Edit 2)

I am reading through the wikipedia page, and it turns out that you shouldn't set len to 9, because if you have for example 153, the other_num should be 1^3 + 5^3 + 3^3 (example from Wikipedia).

So you should adjust the loop in the following way:

unsigned int num;
for (num = 0; num < 1000000000; ++num)
{
char digits[15];
unsigned int i, other_num, len;
len = snprintf(digits, 10, "%u", i); // len returned by snprintf
other_num = 0;
for (j = 0; j < len; ++j) // changed 9 to len
other_num += power(digits[j] - '0', len);
if (num == other_num)
printf(" %d ",num);
}

Edit 2:

I just noticed that your number starts from 100,000,000, so you don't really need to pay attention to Edit 1. Nevertheless, I believe it's good to know it in case you needed to change the range of your numbers.

Why does this for loop exit on some platforms and not on others?

On my laptop running Ubuntu 14.04, this code does not break it runs to completion. On my school's computer running CentOS 6.6, it also runs fine. On Windows 8.1, the loop never terminates.

What is more strange is when I edit the conditional of the for loop to: i <= 11, the code only terminates on my laptop running Ubuntu. CentOS and Windows never terminates.

You've just discovered memory stomping. You can read more about it here: What is a “memory stomp”?

When you allocate int array[10],i;, those variables go into memory (specifically, they're allocated on the stack, which is a block of memory associated with the function). array[] and i are probably adjacent to each other in memory. It seems that on Windows 8.1, i is located at array[10]. On CentOS, i is located at array[11]. And on Ubuntu, it's in neither spot (maybe it's at array[-1]?).

Try adding these debugging statements to your code. You should notice that on iteration 10 or 11, array[i] points at i.

#include <stdio.h>

int main()
{
int array[10],i;

printf ("array: %p, &i: %p\n", array, &i);
printf ("i is offset %d from array\n", &i - array);

for (i = 0; i <=11 ; i++)
{
printf ("%d: Writing 0 to address %p\n", i, &array[i]);
array[i]=0; /*code should never terminate*/
}
return 0;
}

How to run different while loops without breaking any

Your program needs to connect, read and disconnect from two devices, however, it can only have one connection open at a time. Thus, the connections are mutually exclusive. You could use a mutex for that.

Your code suggests, that one connection should be polled indefinitely with a certain timeout, and the other on request via a button. I would simply put both in a slot, one called by the button, the other by a timer, and protect them with a mutex.

Outline:

class MainProgram : QObject {
// Other stuff
private slots:
void on_pushCheck_clicked();
void readPeriodically();

private:
QMutex m_mutex;
QTimer *m_timer;
};

void MainProgram::MainProgram()
{
// other stuff

m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, &MainProgram::readPeriodically);
m_timer->setInterval(2000);
m_timer->start();
}

void MainProgram::on_pushCheck_clicked()
{
QMutexLocker l(&m_mutex);

// Read from device 1
}

void MainProgram::readPeriodically()
{
QMutexLocker l(&m_mutex);

// Read from device 2
}

This assumes that reading will be very quick, as the UI is blocked during this time. If that is not the case, you can put the reading code into a backtround worker thread. This approach is asynchronous, you trigger the read, and the the result some time later:

class DeviceReader : QObject {
public:
void readDevice1();
void readDevice2();

signals:
void device1Data(int);
void device2Data(int);

private:
Q_INVOKABLE void doReadDevice1();
Q_INVOKABLE void doReadDevice2();

private:
QMutex m_mutex;
};

void DeviceReader::readDevice1()
{
// Cross thread boundary
QMetaObject::invokeMethod(this, "doReadDevice1", Qt::QueuedConnection);
}

void DeviceReader::doReadDevice1()
{
QMutexLocker l(&m_mutex);

// Read from device 1

emit device1Data(1);
}

// similar for device 2

MainProgram::MainProgram() {
DeviceReader *r = new DeviceReader;
QThread *t = new QThread;

r->moveToThread(t);

// Connect signals for starting reads, or call them as necessary
// Connect signal to deleteLater on thread when app closes
// e.g. QApplication::aboutToQuit

// The worker object does not have a "working" method.
// It will just listen to events (signals) through the thread's exec loop
t->start();

}

Stop a for loop when user is finished entering input in c

You have received a number of good answers to your question, and there are several more ways to take input of doubles and stop on "done". Since you are learning C, always, ALWAYS (in case it wasn't clear), check the return of scanf to validate the number of conversions you expected actually took place.[1] (this also provides your way to end input on "done" (or any non-double entered causing scanf to return less than 1)

As noted in the comment, arrays are zero based in C. When you are taking input, you will want to use count as your array-index, rather than i (in this case if you exit the read on each failure -- it doesn't matter, but you could just as easily prompt again for additional input and increment count only on a successful return from scanf) Back to your question. If you set up your read loop to continually loop until there is a scanf failure, you can make use of a temporary variable to initially capture the input value, and only assign the value to your array and increment your index on success. e.g. (with a constant MAXD = 1048)

for (;;) {  /* loop until scanf input fails (with 'done') */

double tmp; /* block scope declarations are fine */

printf (" data[%4d]: ", count);

if (count < MAXD && scanf(" %lf", &tmp) == 1)
data[count++] = tmp;
else
break;
}

(you can even move a copy of the prompt above the loop, and move the one above after the if (....) {...} to eliminate the prompt when the array limit (MAXD) is reached -- that's left as an exercise)

In the example above you have 2 conditions you enforce before storing a value. (1) you limit the number of values your user can store to MAXD, and (2) you only store a value if a valid conversion to double takes place in scanf. You leave the loop if either of the conditions fails (which if you enter "done" as a double-value, it will).

Putting the pieces together and dropping a few additional tips in the comments, you could test with something like the following:

#include <stdio.h>

enum { MAXD = 1048 }; /* declare constants instead of using magic numbers */

int main (void) {

double data[MAXD] = {0}; /* in ISO C declarations come before code */
int i, count = 0; /* initializing variable saves debug time */

printf ("\n Welcome! \n\n Please enter each data point. "
"Enter 'done' when finished.\n\n");

for (;;) { /* loop until scanf input fails (with 'done') */

double tmp; /* block scope declarations are fine */

printf (" data[%4d]: ", count);

if (count < MAXD && scanf(" %lf", &tmp) == 1)
data[count++] = tmp;
else
break;
}

printf ("\n %d values entered:\n\n", count);

for (i = 0; i < count; i++)
printf (" data[%4d] : %.2lf\n", i, data[i]);

return 0; /* main() is type 'int' and returns a value */
}

Example Use/Output

$ ./bin/scanfdoubles

Welcome!

Please enter each data point. Enter 'done' when finished.

data[ 0]: 1.1
data[ 1]: 1.2
data[ 2]: 1.3
data[ 3]: 1.4
data[ 4]: 1.5
data[ 5]: 1.6
data[ 6]: done

6 values entered:

data[ 0] : 1.10
data[ 1] : 1.20
data[ 2] : 1.30
data[ 3] : 1.40
data[ 4] : 1.50
data[ 5] : 1.60

Look things over and let me know if you have any questions.

footnotes:

1. while you can use scanf to take user-input in C, you are better off using a line-oriented function (like fgets) and then parsing the complete line (with, e.g. sscanf). The allows you to both (1) validate the read (e.g. the return of fgets) and then (2) separately validate the value entered by the user. This decoupling of your read, and your parsing has many advantages.



Related Topics



Leave a reply



Submit