0

My code finds combination value of any number when the number of places is taken as 4.

#include <iostream>
#include <iomanip> 
using namespace std;

int main() { 
    int n; 
    long double factorial = 1.0; 
    long double fac = 1.0; 
    cout << "Enter a positive integer: "; 
    cin >> n; 
    for(int i = 1; i <= n; ++i) { 
        factorial *= i; 
    } 
    for(int i = 1; i <= n-4; ++i) { 
        fac *= i; 
    } 
    cout << "Com. of " << n << " = " << setprecision(13) << factorial/(24*fac); 
    return 0;
 }

It works fine for values like 79,98,100 etc but the code outputs nan when I input 300, 400

A M
  • 14,694
  • 5
  • 19
  • 44
Leaven
  • 1
  • 1
  • 1
    Welcome to Stack Overflow. "combination value of any number when the number of places is taken as 4" (Did you mean, the result of `n choose 4`?). What do you think the result should be for `n = 100`? Why? What do you think the result should be for `n = 300`? Why? What do you think is the largest value that can be stored in a `long double`? ([Did you try](https://meta.stackoverflow.com/questions/261592/) to [find out](https://duckduckgo.com/?q=c%2B%2B+long+double+maximum)?) – Karl Knechtel Jun 30 '22 at 06:48
  • 2
    Can you think of a simpler way to do the calculation? (Hint: if you actually wrote out all of the multiplications that are supposed to happen in the numerator and denominator, do you see how most of them would cancel out for a large value of `n`?) – Karl Knechtel Jun 30 '22 at 06:50
  • Your values are overflowing, both `fac` and `factorial` are infinity. And infinity/infinity is nan. But Karl is correct, there is an obvious improvement to this calculation. Just think about how you would do this. If you were given say n = 100, would you work it out the way your code does? Or would you find an easier way? – john Jun 30 '22 at 06:54
  • I actually copied the code for gaining factorials from some website and modified it to gain values for nCr where r = 4. I don't understand how long doubles work or how I could make factorials work with just integer values. – Leaven Jun 30 '22 at 06:59
  • @Leaven 100C4 is just 100*99*98*97. That's a lot easier than 100!/96!. – john Jun 30 '22 at 07:01
  • @Leaven There are limits to how big a `long double` can get. You are going over those limits. When you exceed those limits the long doubles are set to infinity. But then you do the division, so you are asking the computer to calculate infinity/infinity. There a special value for the result of that calculation, it's NaN. NaN stands for 'not a number'. And that's what you get as your output. – john Jun 30 '22 at 07:03
  • @Leaven You have to stop thinking that computers do real math. Code can be perfectly correct by the rules of normal mathematics, but completely incorrect by the rules that computers actually follow. – john Jun 30 '22 at 07:05

2 Answers2

1

c++ handles numbers in two different ways: integer overflow or undefined behavior.

To put it simply, in c++, long doubles contain 8 bytes of data. This means you have 64 bits to store the data of your number. If you put in a large number like 300400, consider how large 300400! is (approximately 1.36 * 10 ^ 1515042). It's not a number that can be represented by 64 bits (a long double's maximum value is roughly 1.8 * 10 ^ 308).

In C++, integers will simply overflow. This means that if all the bits in the variable are 1, adding 1 more to that variable will cause everything to reset to 0, causing you to go from the maximum possible value to the minimum possible value. Doubles, by virtue of needing to maintain data regarding where the decimal point is, don't have this behavior, and instead represent themselves as inf, or infinity, in the program. When you try to divide factorial / (24 * factorial), in essence you are telling c++ to divide infinity by infinity, which isn't a number, hence why you're getting nan (i.e. "not a number").

For more information and a more in depth explanation of overflows vs inf, check out this post. For a better explanation of how integers and numbers are represented in binary/to the program, check out this video.

1

n! has a hug growth rate.

if you input more than 100 the fac will be very large

nan is normal

in fact 7998100 also outputs nan

Subsegment
  • 152
  • 6
  • Very large numbers will output as infinity. You've missed the real reason that this code outputs nan. – john Jun 30 '22 at 07:13