1

I am solving a question which finds a value k which is correct up to ~4 decimal points. I have initialized k as a double. However, it only takes 2 places after the decimal point. I want to know the reason behind this bizarre behaviour.

I have experimented with different numbers to try to understand why this is happening but was unsuccessful.

#include <bits/stdc++.h>

using namespace std;

double calc_err(double x, double y, double z, double a, double k)
{
    return ((y*y)/((z-k)*(z-k)) - (a*a*x*x)/(k*k) - (a*a) + 1.0);
}

int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        double x, y, z, a;
        cin >> x >> y >> z >> a;

        double cerrp = 100.0;
        double hi = z;
        double lo = 0;
        while(1)
        {
            cout << "cerrp : " << cerrp << endl;
            double k  = (hi + lo)/2;
            if (cerrp  < 0.00005 && cerrp >= 0.0 )
            {
                cout << "k final : " << k << endl;
                break;
            }
            cout << "hi : " << hi << endl;
            cout << "lo : " << lo << endl;
            cout << "k : " << k << endl;
            cerrp = calc_err(x, y, z, a, k);
            if (cerrp >= 0) hi = k;
            else lo = k;


        }
    }
}

Consider the following input: 1 7390 8573 9287 285

After a certain number of iterations "hi" takes a value 9263.49 and "lo" takes a value 9263.48. Hence I expect "k" to take a value (hi + lo)/2 = 9263.485 but it takes the value 9263.49. Also, note that "cerrp" keeps on changing even when "k" is not changing (all the other parameters are constant). Why is this happening?

Edit: This is different from Is floating point math broken? in that my question is related to the precision of the variable while displaying it while the question in the link is related to the inherent inaccuracies of floating point operations.

Evil_Transistor
  • 188
  • 1
  • 1
  • 10
  • 2
    Possible duplicate of [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Fureeish Feb 17 '19 at 14:45
  • https://en.cppreference.com/w/cpp/io/manip/setprecision also https://randomascii.wordpress.com/2013/07/16/floating-point-determinism/ – Jesper Juhl Feb 17 '19 at 14:47
  • 1
    When you talk about the value of 'k', do you mean in the debugger (aka the value stored in the variable), or what is displayed when calling std::cout ? Those are two very different things. – AlexG Feb 17 '19 at 14:51
  • 1
    A double doesn't have decimal digits either before or after the decimal point. It has binary digits, and the two are not commensurable. – user207421 Feb 17 '19 at 14:53
  • Your problem is just about precision when you print the values, look at my answer – bruno Feb 17 '19 at 14:53
  • 1
    Precision is measured in significant digits, not decimals. The default output format precision is six significant digits. – molbdnilo Feb 17 '19 at 14:56
  • @molbdnilo while the number have less digits before the dot than the current precision, to have an higher precision will give more digits after the dot ^^ – bruno Feb 17 '19 at 15:02

1 Answers1

2

Just use std::setprecision() for more digits when you print

For instance with

int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        double x, y, z, a;
        cin >> x >> y >> z >> a;

        double cerrp = 100.0;
        double hi = z;
        double lo = 0;
        while(1)
        {
            cout << "cerrp : " << std::setprecision(10) <<cerrp << endl;
            double k  = (hi + lo)/2;
            if (cerrp  < 0.00005 && cerrp >= 0.0 )
            {
                cout << "k final : " << std::setprecision(10) << k << endl;
                break;
            }
            cout << "hi : " << std::setprecision(10) << hi << endl;
            cout << "lo : " << std::setprecision(10) << lo << endl;
            cout << "k : " << std::setprecision(10) << k << endl;
            cerrp = calc_err(x, y, z, a, k);
            if (cerrp >= 0) hi = k;
            else lo = k;


        }
    }
}

Execution with input 1 7390 8573 9287 285

cerrp : 100
hi : 9287
lo : 0
k : 4643.5
cerrp : -286945.888
hi : 9287
lo : 4643.5
k : 6965.25
cerrp : -172643.8308
hi : 9287
lo : 6965.25
k : 8126.125
cerrp : -148345.0696
hi : 9287
lo : 8126.125
k : 8706.5625
...
hi : 9263.485111
lo : 9263.485111
k : 9263.485111
cerrp : -8.219334995e-05
hi : 9263.485111
lo : 9263.485111
k : 9263.485111
cerrp : 1.337719732e-05
k final : 9263.485111
bruno
  • 32,421
  • 7
  • 25
  • 37