0

I have a console app with a function that divides integers of a Fibonacci series, demonstrating how the ratio in any Fibonacci series approaches Φ . I have simliar code written in Go and inC++11. InGo (or a scientific calculator), the function returns values of int64 and the results show a precision of up to 16 digits in an Ubuntu Terminal Session, for example:

1.6180339937902115

In C++11 I can never see more that 5 digits of precision in the results usingcout. The results are declared aslong double in a function like this:

typedef unsigned long long int ULInt;
typedef std::vector< ULInt> ULIntV;

std::vector<long double > CalcSequenceRatio( const ULIntV& fib )
{

    std::vector<long double> result;

    for ( int i = 0; i != fib.size( ); i ++ )
    {
         if ( i == ( fib.size( ) - 1 ) )
         {
             result[i] = 0;
             break;
          }

    long double n = fib[i + 1];
    long double n2 = fib[i];
    long double q = n / n2;

    result.push_back( q );

  }
     return result;
 }

Although the vectorfib passed into CalcSequenceRatio( const ULIntV& fib ) contains over 100 entries, after 16 entries, all values in the result set are displayed as

1.61803

The rest of the value is being rounded although in Go (or in a calculator), I can see that the actual values are extended to at least 16 digits of precision.

How can I make CalcSequenceRatio() return more precise values? Is there is problem because going from long long int to long double is a downcast? Do I need to pass the fib series as vector<long double>? What's wrong?

Edit:

This question has been marked a duplicate, but this is not really correct, because the question does not deal directly with cout: There are other factors that might have made a difference, although the analysis proves that cout is the problem. I posted the correct answer:

The problem is with cout, and here is the solution... as explained in the other question...

Vector
  • 10,879
  • 12
  • 61
  • 101
  • There is a school of thought that iostream is evil. See the Google C++ Style doc http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=Streams#Streams – SzG Apr 20 '14 at 18:50
  • 1
    @comeAndGo: Well, just because some other language does something else is no reason to categorize the question as relevant to that other language in any way. Please don't do so. – Deduplicator Apr 20 '14 at 18:51
  • @R.MartinhoFernandes - IMO adjusting the precision of `cout` should not be referred to as simply a _display issue_ , which is rather meaningless and certainly not helpful, particularly since the terminal emulator can probably display as much precision as you want. – Vector Apr 20 '14 at 20:42
  • @Deduplicator - I removed it because I have the correct answer, which has nothing to do with Go at all. But your contention is IMO not correct. Not knowing the answer, it was possible that there was a difference between Go's `int64` and C++'s `long double`that an expert in both languages might have known about. (As an aside, _Please don't do so_ is a bit rude - do you make the rules here more than everyone else?) – Vector Apr 20 '14 at 20:46
  • @comeAndGo: I don't make the rules more than anyone else, but if noone remarks on violation of rules, there are none. And you really would not want that... That aside, how would you clearly and concisely inform someone he uses a bad tag for his question? I don't see how my remark could be construed as being rude. – Deduplicator Apr 20 '14 at 20:50
  • @Deduplicator : _don't do so_ is imperative - **an order** - you have passed judgement and I am mandated to comply. Check the English Language site... The _please_ doesn't make any difference - it's rude. Try - _maybe consider rethinking this tag - I don't see how it fits the question._ See the difference? – Vector Apr 20 '14 at 20:55
  • And this is a bad question because?... or is someone just miffed? Downvoting without stating a reason in this case is not at all helpful... – Vector Apr 20 '14 at 21:00
  • Bad question? I never said anything about the question being bad nor downvoted, I just said that your reason for categorising it as `language Go` goes against the grain, and asked politely (You did see the `please` you dropped from your quote?) to therefore refrain from using that tag. May I reiterate my request for how you would have wanted it phrased clearly, concisely and politely? – Deduplicator Apr 20 '14 at 21:05
  • @Deduplicator - as per chat and my comment above _May I reiterate my request..._ has been answered. – Vector Apr 20 '14 at 21:33
  • @comeAndGo it's an issue with the mechanism used to display the data, not the data. Seems meaningful to me :| – R. Martinho Fernandes Apr 21 '14 at 01:53
  • @SzG - great reference. Important. Tnx. Now I know why `Go` doesn't support streams... – Vector Apr 21 '14 at 02:28
  • @R.MartinhoFernandes - Actually the issue regarding `cout` is not a **display issue**, at all, it's a **data representation** issue, and the same question is relevant to other functions in `iostream` where display is not relevant-it could be a question relevant to pure calculations, regarding how the value is represented in the classes of `iostream`. See SzG's comment and **reference** above. – Vector Apr 21 '14 at 03:51

2 Answers2

3

It sounds like you want to use: std::numeric_limits<T>::max_digits10 for distinct, 'round-trip' conversions - in conjunction with std::setprecision.

e.g., for float this is typically (9) => or 1.8 format. double is typically (17) => 1.16

A long double is typically implemented as an 80 bit extended precision type on x86, or a 128 bit quad precision type, with (21) => 1.20 and (36) => 1.35 formats respectively. However the long double is only required to provide at least as much precision as a double.

There's a good series of notes on related subjects here.

Brett Hale
  • 21,653
  • 2
  • 61
  • 90
0

The problem here is withstd::cout.

I fixed it using std::setprecision(50), as explained in How do I print a double value with full precision using cout? That shows me values like this:

1.6180339887498948482072100296669248109537875279784

To make it flexible, I gave the user the option to enter the desired level of precision:

void printGolden( const std::vector<long double>& golden )
{
    cout << "Enter desired precision:" << endl;
    int precision{};
    cin >> precision;
    std::cout << std::setprecision( precision );
    for ( auto i : golden )
    {
      std::cout << i << "; ";
    }

}

Community
  • 1
  • 1
Vector
  • 10,879
  • 12
  • 61
  • 101
  • 1
    You should pass your vector by reference to const. Also I would advise to reset the precision to its previous value once your printing is done. – quantdev Apr 20 '14 at 23:35
  • @karim - yes, I am aware of these issues - just threw up some code quickly for demo. Fixed `const &` . Tnx. – Vector Apr 21 '14 at 00:53
  • Unexplained downvotes are not constructive. You have a complaint? Please register it - IMO this is a perfectly correct and valid answer. – Vector Apr 21 '14 at 04:06