C++ Primer ex 7.20 - finding factorial

A

arnuld

it runs fine. any advice for the improvement:

/* C++ Primer - 4/e
*
* exercise 7.20
* STATEMENT:
* write a programme to find the factorial of an int.
* use an iteratice function.
*
*/

#include <iostream>

long double find_factorial( int num ) {
/* maximum value of 32 bit int is 32768. so we need to use
long double to store its factorial value, but still for any values
above 1754 i get "inf" as output. i dont't have any problem with that
kind of output as i have successfully created the iterative version
of the factorial function.
*/

long double facto = 1;

for(int i = num; i != 0; --i)
{
facto *= i;
}

return facto;
}


int main()
{
std::cout << "Enter the number: ";
int i;
std::cin >> i;

std::cout << "Factorial of "
<< i
<< " = "
<< find_factorial( i )
<< std::endl;
return 0;
}
 
O

Obnoxious User

it runs fine. any advice for the improvement:

/* C++ Primer - 4/e
*
* exercise 7.20
* STATEMENT:
* write a programme to find the factorial of an int.
* use an iteratice function.
*
*/

#include <iostream>

long double find_factorial( int num ) {
/* maximum value of 32 bit int is 32768. so we need to use

2^32 != 32768
 
J

Juha Nieminen

arnuld said:
ok, whatever the value is,

Shouldn't you familiarize yourself on how numbers and numeric limits
work in computers?
Believing that 32768 is the largest value representable with a 32-bit
integer shows a great lack of understanding about integers and amounts
of bits.
the point is: "long doouble" is not going to
handle any value greater than the factorial of 1754.

A long double is not going to give you an *accurate* result from some
value forward. When the result is large enough the last digits will be
wrong, and thus the result will be wrong. It's not the factorial of the
given number.
 
P

Philip Potter

Juha said:
A long double is not going to give you an *accurate* result from some
value forward. When the result is large enough the last digits will be
wrong, and thus the result will be wrong. It's not the factorial of the
given number.

But with factorials, the trailing digits are all zeroes (in any base),
so perhaps a floating-point number is appropriate.

The largest factorial a 32-bit long can hold is 12! or 479001600. This
number in binary has 10 trailing zeroes and so can be accurately
represented with a 19-bit mantissa (stored in 18 bits with the first bit
"hidden") and 5-bit exponent; thus including sign bit, only 18+5+1 = 24
bits are required to store this number in floating-point.

Similarly, an IEEE 754 single-precision (32-bit) number can store up to
13! or 6227020800 accurately.

(I'd still advocate using integer types for factorials unless you
*really* know what you're doing...)
 
T

tom

it runs fine. any advice for the improvement:

/* C++ Primer - 4/e
*
* exercise 7.20
* STATEMENT:
* write a programme to find the factorial of an int.
* use an iteratice function.
*
*/

#include <iostream>

long double find_factorial( int num ) {
/* maximum value of 32 bit int is 32768. so we need to use
long double to store its factorial value, but still for any values
above 1754 i get "inf" as output. i dont't have any problem with that
kind of output as i have successfully created the iterative version
of the factorial function.
*/

long double facto = 1;

for(int i = num; i != 0; --i)
{
facto *= i;
}

return facto;

}

int main()
{
std::cout << "Enter the number: ";
int i;
std::cin >> i;

std::cout << "Factorial of "
<< i
<< " = "
<< find_factorial( i )
<< std::endl;
return 0;

}

--http://arnuld.blogspot.com

can you have a statement:
"using namespace std;"
ahead, and write:
"cout<<...<<endl;"
without referring to "std" every time, it do increase much of the
readibility
 
B

BobR

tom said:
can you have a statement:
"using namespace std;"
ahead, and write:
"cout<<...<<endl;"
without referring to "std" every time, it do increase much of the
readibility

NO, it decreases the 'readibility'!

Can be bad. Try this:

#include <iostream> // #include <ostream> // for std::endl
#include <sstream>
using namespace std;

int main(){
std::eek:stringstream cout;
cout << "hello, world" << std::endl;
std::cout<<cout.str()<<std::endl;
return 0;
} // main()

Remove the 'using namespace std;' line, and it will compile and run as
expected.
 
W

werasm

BobR said:
tom <[email protected]> wrote in message...
NO, it decreases the 'readibility'!

I've become accustomed to typing std without thinking, but...
Can be bad. Try this:

#include <iostream> // #include <ostream> // for std::endl
#include <sstream>
using namespace std;

int main(){
std::eek:stringstream cout;
cout << "hello, world" << std::endl;
std::cout<<cout.str()<<std::endl;
return 0;
} // main()

.... in reality <using namespace> is only used in source/.c* files
and these kind of mistakes like the one mentioned here
above are local to source files (apart from the naivety of
calling something cout, which does not happen in practice
that often (IMhO).
Remove the 'using namespace std;' line, and it will compile and run as
expected.

Yes, rename it (cout) to mystream, or main_cout, or whatever and
it should also compile/run as expected ;-)

Regards,

Werner
 
B

BobR

werasm said:
... in reality <using namespace> is only used in source/.c* files
and these kind of mistakes like the one mentioned here
above are local to source files (apart from the naivety of
calling something cout, which does not happen in practice
that often (IMhO).


Yes, rename it (cout) to mystream, or main_cout, or whatever and
it should also compile/run as expected ;-)

My use of 'cout' was not a mistake.

The point is that if you use the 'using namespace std;' you will eventually
name something that is defined in the std namespace, and it could bite you.
Most times it will just cause a compiler diagnostic (.. and save your
behind. <G>).

I used the 'cout' example because that is what I actually use in my
TestBench program. I got tired of makeing a separate program to test
snippets posted in these NGs. So, now I just cut/paste/compile/run in many
cases.
Since TestBench is an wxWidgets (windows) program, std::cout is useless
(unless it's re-directed, which I don't have to do now). My 'cout' is sent
on to the wxTextCtrl window for output. Not perfect, but easier than before.
And I don't have to drop out of the GUI to a command-line.
 
W

werasm

BobR said:
My use of 'cout' was not a mistake.

I realize this, hence my comment that I deem the deliberate use
unrealistic in practice, and deliberately named as such in this
case to prove a point. My point is that in practice these name
clashes are rare (if <using namespace std> is confined to
source files. That said, I've become so accustomed to
typing std, that I do it without thinking, making <using
namespace std> useless anyway.

All said, I have come across library implementations that
have more than one version of endl/cout etc (admittedly
more than 5 years ago, and not qualifying by std explicitly
gave me strange errors then (wrong one selected), especially
concerning endl/ends.
The point is that if you use the 'using namespace std;' you will eventually
name something that is defined in the std namespace, and it could bite you.
Most times it will just cause a compiler diagnostic (.. and save your
behind. <G>).

My point is that this <is> rare enough to merit "using namespace std".
Although, I disagree that adding std makes code less readable. For me
it makes no difference in the readability, on the contrary.
Since TestBench is an wxWidgets (windows) program, std::cout is useless
(unless it's re-directed, which I don't have to do now). My 'cout' is sent
on to the wxTextCtrl window for output. Not perfect, but easier than before.
And I don't have to drop out of the GUI to a command-line.

We've done similar things to output to qWidget, or whatever the
classes name was.

Kind regards,

Werner
 
W

werasm

arnuld said:
it runs fine. any advice for the improvement:

Not much, apart from the <int> argument that allows for the
possibility of infinite iteration. I have two other versions
that fallout if infinity is reached. It has the disadvantage
that it does the extra check per iteration, but it will never
iterate more than required. Also, if pedantic, I would
criticize your main function for not ensuring correct
input. If cin failed, you would be using an uninitialized
variable (I'm actually not sure whether this is undefined
behavior). I could come up with two (other) versions. I suppose
the terseness could be criticized. I like the while version as
it causes one less iteration (not that it matters).

#include <iostream>
#include <climits>

long double factorial_1( unsigned value )
{
static long double inf( std::numeric_limits<long
double>::infinity() );
long double result( 1 );
for( unsigned i = 0; (i < value) && (result < inf); result *= ++i )
{ }
return result;
}

long double factorial_2( unsigned value )
{
static long double inf( std::numeric_limits<long
double>::infinity() );
long double result( value );
while( --value )
{
result *= value;
if( result == inf ){ break; }
}
return result;
}

int main()
{
enum{ error = -1, success = 0 };
std::cout << "Enter value" << std::endl;
unsigned value;

if( std::cin >> value )
{
std::cout << "Result: " << factorial_1( value ) << std::endl;
return success;
}
else
{
std::cout << "Input error!" << std::endl;
return error;
}
}

Regards,

Werner
 
W

werasm

werasm wrote:

[SNIP]

Some corrections :)
#include <climits>

should be...

#include <limits>

and...
static long double inf(
std::numeric_limits<long> double>::infinity() );

should be:

const static long double inf(
std::numeric_limits<long> double>::infinity() );

Regards,

W
 
J

Joel Yliluoma

I realize this, hence my comment that I deem the deliberate use
unrealistic in practice, and deliberately named as such in this
case to prove a point.

How unrealistic is it that you might happen to use
something like "includes", "unique", "replace" or
"reverse" in your program as a variable or a function?
All of those are names of functions in <algorithm>.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

C++ Primer ex 5.18 5
C++ Primer ex 7.14 2
C++ Primer ex 7.5 18
C++ Primer ex 7.12 2
C++ Primer ex 4.30 10
C++ Primer ex 9.27 4
C++ Primer ex 3.14 8
C++ Primer ex 6.20 36

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top