While working only when std::cout is used

I have encountered an unusual problem: I have a while(1) loop that will break after a few iterations, but it doesn't break (the program freezes when it reaches it). To make matters more peculiar, the same loop works with the exact same parameters when i add a call to std::cout.

Code:
1
2
3
4
5
6
7
8
9
10
11
12
std::pair<int, int> Fraction(double in){
    double tmp = in;
    int tmp2 = 0;
    while(1){
        tmp *= 10;
        tmp2++;
        //std::cout << "2";
        if(tmp == (int)tmp)
            break;
    }
    return std::make_pair(int(tmp), int(Power(10.0, double(tmp2))));
}


There must be a simple solution to this, but nothing like this has ever happened to me in my 2 years of programming.
Thanks in advance for any help.
Last edited on
What is the ultimate purpose of your code? Why do you need to find a fractional representation of a double?

int-double equality is very finicky due the inherent nature of floating-point numbers, so your line 8 seem really out of place, and maybe shouldn't be relied on.

So it sounds like it creates an infinite loop when you don't have the std::cout in there.
That sounds like some weird, undefined behavior that just so happens to work due to the specific conditions. My guess is that when you try to cast tmp to an int, you invoke an integer overflow, which is undefined behavior. After that, your program is completely invalid and any behavior is possible.

Is it possible for you to reduce the problem so that you can make a complete example that still reproduces your problem?

______

Okay, so you're trying to convert a double to an integer numerator and denominator. May I ask why? Going from a fraction to a double is easy; the reverse is difficult due to the nature of floating-point numbers. This is really prone to error, because it's possible that two very large integers are required to represent your fraction, which causes undefined behavior if they overflow.
Last edited on
Thanks for the reply. My function is supposed to take in a decimal number and output it in the form of a fraction of two integers (for example 0.254 -> 254 / 1000, hence the pair of ints). Also, after some fiddling, I discovered that any function that takes time to execute that is put between line 6 and 8 makes it work. Line 8 is supposed to check whether the number is whole or not (if you have a suggestion to do it in a better way, please tell me).

Edit: To better explain "any function that takes time to execute", I mean functions that either wait for something (like sleep) or rely on slow system calls (std::cout on windows 10).
Last edited on
The only way you could hope to do this is to enter the number as a string, not a double You can then pick off the part after the decimal point directly as an integer (e.g. by putting the substring through a stringstream.

Floating-point numbers are stored only to their nearest representation in binary, so unless your number happens to be precisely representable in binary your answer will always be inaccurate and/or ambiguous.

1
2
3
4
5
6
7
8
9
#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
   double x = 0.254;
   cout << "0.254 =" << setprecision(25) << fixed << x << endl;
}


0.254 =0.2540000000000000035527137

What fraction would you like to represent it as?
Last edited on
In reply to your edit, I am aware of the dangers if the numbers are large and that's why I won't use large numbers, but thanks for the warning. I need the function for getting powers with an exponent that is not a whole number
(nx / y = yroot(nx)).
Last edited on
I still think that your tmp variable is overflowing. Try printing the value of temp and temp2 each iteration. Putting stuff between 6 and 8 is probably behavior that shouldn't be relied upon, since we're dealing with undefined behavior.

This link might help. The question is about how to represent a double as a fraction.
https://stackoverflow.com/questions/26643695/converting-decimal-to-fraction-c

_______________

Also, note that 2^31 - 1 = 2,147,483,647 (this is the max signed 32-bit value on many systems)
This is between 10^9 and 10^10. So if your tmp2 variable goes to 9 and then beyond, you probably have undefined behavior.
when you store 0.254 in type double, you're not actually storing 254 / 1000, because that's not a value a variable of that type can assume. 254/1000 lies between two valid doubles: 0.253999999999999948041562447542673908174037933349609375 and 0.254000000000000003552713678800500929355621337890625. It is a little closer to the second one, so whenever you write "0.254" in source code, you're actually writing "0.254000000000000003552713678800500929355621337890625", or, 0x1.04189374bc6a8p-2 in hex.

To be fair, multiplying that particular double by 10 three times under the rules of double arithmetic does end up giving an integer: with that input, your loop is solved in compile time by by both gcc and clang: https://godbolt.org/g/YJtzvD (note what the main function compiled to)

As Ganado said, you need a complete example that still reproduces your problem.
Last edited on
I see now. Thank you for your answers. I forgot about that.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <string>
using namespace std;

//======================================================================

int hcf( int a, int b )
{
   int q = 1;

   while ( b > 0 )
   {
      q = b;
      b = a % q;
      a = q;
   }
   return q;
}

//======================================================================

pair<int,int> rationalise( string x )            
{
   int pos = x.find( "." );
   // Still to do: deal with cases of no decimal point, or no whole-number or decimal parts

   int whole     = stoi( x.substr( 0, pos  ) );
   int numerator = stoi( x.substr( pos + 1 ) );

   int denominator = 1;
   while ( denominator <= numerator ) denominator *= 10;   // next power of 10
   int factor = hcf( numerator, denominator );             // simplify fraction
   numerator /= factor;
   denominator /= factor;

   if ( whole < 0 ) numerator = -numerator;
   numerator += whole * denominator;                       // include whole number in denominator

   return { numerator, denominator };
}

//======================================================================

int main()
{
   const string x[] = { "0.254" , "6.10", "3.14", "-12.400" };
   pair<int,int> f;

   for ( string s : x )
   {
      f = rationalise( s );
      cout << s << " = " << f.first << '/' <<  f.second << '\n';
   }
}

//====================================================================== 

0.254 = 127/500
6.10 = 61/10
3.14 = 157/50
-12.400 = -62/5
Last edited on
Topic archived. No new replies allowed.