Why does std::cout.flush doesn't flush at the end of a loop ?

Hi everyone, here's the piece of my code relevant for this question:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

int speed = 5*n/100;

for(int j=0; j < 3; ++j)    
{
    for(int i = 0; i < n; ++i)
    {
          if( ((double)i/speed) - (i/speed) == 0)
          {
               std::cout<<"\x1B[s"<<i*100/n<<"%"<<std::flush <<"\x1B[u";
               std::cout.flush();
          }
    }
}


As the n is a huge number, so I am showing the percentage progress
every every 5%.. . It works perfectly for j=0,1, shows the progress and flushes it out.. except after the third (final) loop 99% stays hanging there ! I don't want that.. and I don't understand why std::cout.flush(); doesn't flush it out !

I am stuck here ... any help will be really appreciated :)
Last edited on
Hi,

Try to avoid using equality comparison for double in a conditional. Floating point numbers don't have exact representation.

To do equality, you need to find the absolute value of the difference between the your number and the expected number, if this value is less than some precision value you specify - then it is "close enough".

For example, if you specified 0.1 as the precision value, the expected value is 100.0, and your number is 99.91, then that function should return true.

Also be careful with integer division, on lines 2 and 8 and possibly 10 (depending on type and value of n), you could have value of 0 there.

Avoid C style casts, they are not as safe as the C++ cast:

double iAsDouble = static_cast<double>(i);

http://en.cppreference.com/w/cpp/language/static_cast

There are compiler warnings that will help with all this. If you don't use g++ , then you may find the equivalent in your compiler.

Edit: sometimes one does want integer divsion, I am saying be careful with it.
Last edited on
Hi @TheIdeasMan thanks for your reply and I am aware of the precision situation, in fact in the step int speed = 5*n/100; I have an 5*n >= 100 so I am safe and even if that is not true, I will not have a "percentage progress" printed on my screen and I am happy with that. About the condition

 
if( ((double)i/speed) - (i/speed) == 0)


For example, if you specified 0.1 as the precision value, the expected value is 100.0, and your number is 99.91, then that function should return true.
, I agree completely... but I am not concerned about slight rounding off discrepancies near the edges.

Suppose that: (1) The condition is always satisfied... that means the percentage progress will be shown always. (2) The condition is never satisfied, the progress will be never shown.

But this should not have anything to do with the behavior of flush. 99% or whatever % printed or not printed should still be flushed out.. right ?
Alright, try looking at the program in a debugger, see what the values are just before the loops finish.

Just to be clear on what the problem is - you are saying the last value to be printed is 99% and that is not what you want. Presumably you want it to display 100% or to say that it is finished?

99% or whatever % printed or not printed should still be flushed out.. right ?


That doesn't make sense to me. How can you have not printed but still flushed? Not printing something comes from your if condition, flushing means forcing whatever is the buffer to be displayed.

Can you post something we can compile? Please show the output you are expecting, and the output you are getting.

I still think your if condition is nasty in a subtle way. Experience shows that mixing double and int expressions, and equality with zero for a double type, almost always has problems.

Oh, the extra compiler options:
http://www.cplusplus.com/forum/general/183731/#msg899203

Edit: When dealing with doubles, always put digits before and after the decimal point:

if( ((double)i/speed) - (i/speed) == 0.0)

Last edited on
Just to be clear on what the problem is - you are saying the last value to be printed is 99% and that is not what you want. Presumably you want it to display 100% or to say that it is finished?


Sorry for not being clear. No, that's not what I want ! I have no problem with any x% printed, I just want it to be erased from the terminal once I move past the loop ! For any loop but the final (j loop), I see the progress... 1%, 55%, 99% whatever and after the loop ends everything gets erased and then again starting from 0, 1 % etc in the next round... and so on.. nice... but after the last round, that is (j = 3 or whatever the final external loop is) that final x% (98 or 99 or 100% ) printed on the screen doesn't get erased !! It stays on the terminal forever... :-( I want it to be gone !


By the way, in my .bash_aliases I have set:

 
alias g+='g++ -Wall -Wextra -Werror -pedantic -std=c++14'


So I use "g+" for compiling my codes.


 
if( ((double)i/speed) - (i/speed) == 0)


I expect, (double) i/speed = x.y and i/speed = x , where x, y are integers, when i > speed, x != 0 otherwise x = 0 . Whenever i will be an integral multiple of speed , I expect we will have y = 0 too and hence a match. This is a rough condition but I think it should not interfere with the function std::flush. The piece of code that I have provided above, doesn't reproduce my problem.. anyone can check this out by taking a large enough n , (n much greater than speed). But in my real code, I have this kind of loop and after that I call a function... that does something else and prints other stuff on my terminal that doesn't need to be flushed out.


I am not at all an expert in c++ and I am sure you (@TheIdeasMan) have reasons to believe that the precision stuff probably has something to do with the flush . But applying my simple numerical logic :) I can't find clues that can connect the two seemingly unrelated issues. Of course I am wrong somewhere....

I will try your suggestion:

Edit: When dealing with doubles, always put digits before and after the decimal point:

Last edited on
but after the last round, that is (j = 3 or whatever the final external loop is) that final x% (98 or 99 or 100% ) printed on the screen doesn't get erased !! It stays on the terminal forever... :-( I want it to be gone !

The reason it "gets erased" on the first loops is because you write over it. After the third loop, you don't write over it.

Try something like:
1
2
3
4
5
6
7
8
9
10
11
12
13
int speed = 5*n/100;

for(int j=0; j < 3; ++j)    
{
    for(int i = 0; i < n; ++i)
    {
          if( ((double)i/speed) - (i/speed) == 0)
          {
               std::cout<<"\x1B[s"<<i*100/n<<"%" <<"\x1B[u" << std::flush;
          }
    }
}
std::cout << "\x1B[s" << "     " << "\x1B[u" << std::flush;
By the way, in my .bash_aliases I have set:

alias g+='g++ -Wall -Wextra -Werror -pedantic -std=c++14'


That's fine but I was referring to these ones as well:

-Wfloat-equal
-Wconversion
-Wfloat-conversion


Note that these are not enabled by the above warnings options.

The -Wfloat-equal is there for a reason, as I stated earlier FP comparison is error prone.

With great respect towards cire, can I continue to stubbornly object to the if condition?

cire has educated me in the past: double can exactly represent integers up to 32 bit in size. I know you are looking for integral multiples, but the trouble is that you have division. Both 10 and 1 can be represented exactly, but after division as double 0.1 cannot be. There will be many other values which will have this same problem. I can't help but think that if your code worked, then it was luck: you happened to have values that were able to be represented exactly.

Edit: It's ok if the values are equal :+) but not ok if the values are a multiple However, avoid doubles altogether:

Seen as you are after integral multiples, why can't you do modulus?
if (i % speed == 0) {

Last edited on
Topic archived. No new replies allowed.