By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,996 Members | 884 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,996 IT Pros & Developers. It's quick & easy.

C++ Primer ex 7.3

P: n/a
i wanted to know if that's a good design style (upto the knowledge i have
gained till chpater 7):

/* C++ Primer - 4/e
*
* exercise 7.4
* STATEMENT
* write a programme to take two int paramaters and generate the
result of raising the first to the power of the second. write a
programme to call your function passing it two ints. verify the
result.
*
*/

#include <iostream>

int raise_power(int x, int y)
{
int mult = 1;

while( y )
{
mult = mult * x;
--y;
}

return mult;
}

int main()
{
int i = 2;
int j = 3;
int mult_result = 8;

std::cout << static_cast<bool>(mult_result == raise_power(i, j))
<< std::endl;
/* well, never got converted to "true", it alwasy remains 1 :( */
return 0;
}


--
http://arnuld.blogspot.com

Aug 9 '07 #1
Share this Question
Share on Google+
20 Replies


P: n/a
On Aug 8, 9:59 pm, arnuld <geek.arn...@gmail.comwrote:
i wanted to know if that's a good design style (upto the knowledge i have
gained till chpater 7):

/* C++ Primer - 4/e
*
* exercise 7.4
* STATEMENT
* write a programme to take two int paramaters and generate the
result of raising the first to the power of the second. write a
programme to call your function passing it two ints. verify the
result.
*
*/

#include <iostream>

int raise_power(int x, int y)
I would suggest using more meaningful variable names other than 'x'
and 'y'. 'base' and 'exponent' come to mind.
{
int mult = 1;

while( y )
If 'y' is a negative number (which is allowed since it's defined as an
int), this while condition will cause a major bug n your program.
{
mult = mult * x;
--y;
Your while condition is wrong. But if it was correct, you could have
simply written "while( y-- )" to achieve the same result without the
stand-alone decrement.
}

return mult;

}

int main()
{
int i = 2;
int j = 3;
int mult_result = 8;

std::cout << static_cast<bool>(mult_result == raise_power(i, j))
<< std::endl;
/* well, never got converted to "true", it alwasy remains 1 :( */
return 0;

}

--http://arnuld.blogspot.com

Cheers,
Andre

Aug 9 '07 #2

P: n/a
arnuld wrote:
i wanted to know if that's a good design style (upto the knowledge i have
gained till chpater 7):

/* C++ Primer - 4/e
*
* exercise 7.4
* STATEMENT
* write a programme to take two int paramaters and generate the
result of raising the first to the power of the second. write a
programme to call your function passing it two ints. verify the
result.
*
*/

#include <iostream>

int raise_power(int x, int y)
{
int mult = 1;

while( y )
{
mult = mult * x;
--y;
}

return mult;
}
That's OK for positive numbers, but what about negative?
int main()
{
int i = 2;
int j = 3;
int mult_result = 8;

std::cout << static_cast<bool>(mult_result == raise_power(i, j))
<< std::endl;
Be brutal,

assert( raise_power(i, j) == mult_result );

Don't forget to include <cassert>

--
Ian Collins.
Aug 9 '07 #3

P: n/a
On Aug 9, 10:14 am, Ian Collins <ian-n...@hotmail.comwrote:
arnuld wrote:
...[SNIP]...
std::cout << static_cast<bool>(mult_result == raise_power(i, j))
<< std::endl;
Be brutal,

assert( raise_power(i, j) == mult_result );

Don't forget to include <cassert>
that raises an error:

/home/arnuld/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra
ex_07-03.cpp
ex_07-03.cpp: In function 'int main()':
ex_07-03.cpp:32: error: no match for 'operator<<' in 'std::cout <<
((raise_power(i, ((unsigned int)j)) != mult_result) ?
__assert_fail(((const char*)"mult_result == raise_power(i, j)"),
((const char*)"ex_07-03.cpp"), 32u, ((const char*)(&
__PRETTY_FUNCTION__))) : 0)'
/usr/lib/gcc/i686-pc-linux-gnu/4.2.1/../../../../include/c++/4.2.1/
ostream:112: note: candidates are: std::basic_ostream<_CharT,
_Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)
(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits =
std::char_traits<char>]
line 32, is where i use "assert".

Aug 9 '07 #4

P: n/a
On Aug 9, 10:21 am, arnuld <geek.arn...@gmail.comwrote:
that raises an error:

/home/arnuld/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra
ex_07-03.cpp
ex_07-03.cpp: In function 'int main()':
ex_07-03.cpp:32: error: no match for 'operator<<' in 'std::cout <<
((raise_power(i, ((unsigned int)j)) != mult_result) ?
__assert_fail(((const char*)"mult_result == raise_power(i, j)"),
((const char*)"ex_07-03.cpp"), 32u, ((const char*)(&
__PRETTY_FUNCTION__))) : 0)'
/usr/lib/gcc/i686-pc-linux-gnu/4.2.1/../../../../include/c++/4.2.1/
ostream:112: note: candidates are: std::basic_ostream<_CharT,
_Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)
(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits =
std::char_traits<char>]

line 32, is where i use "assert".
sorry, forgot to post code:

std::cout << assert(mult_result == raise_power(i, j))
<< std::endl;
Aug 9 '07 #5

P: n/a
arnuld wrote:
>On Aug 9, 10:21 am, arnuld <geek.arn...@gmail.comwrote:
that raises an error:

/home/arnuld/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra
ex_07-03.cpp
ex_07-03.cpp: In function 'int main()':
ex_07-03.cpp:32: error: no match for 'operator<<' in 'std::cout <<
((raise_power(i, ((unsigned int)j)) != mult_result) ?
__assert_fail(((const char*)"mult_result == raise_power(i, j)"),
((const char*)"ex_07-03.cpp"), 32u, ((const char*)(&
__PRETTY_FUNCTION__))) : 0)'
/usr/lib/gcc/i686-pc-linux-gnu/4.2.1/../../../../include/c++/4.2.1/
ostream:112: note: candidates are: std::basic_ostream<_CharT,
_Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)
(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits =
std::char_traits<char>]

line 32, is where i use "assert".

sorry, forgot to post code:

std::cout << assert(mult_result == raise_power(i, j))
<< std::endl;

No, just use what I wrote.

--
Ian Collins.
Aug 9 '07 #6

P: n/a
On Aug 9, 11:12 am, Ian Collins <ian-n...@hotmail.comwrote:
No, just use what I wrote.

i did use that, now i just modified it to:

std::cout << std::assert( raise_power(i, j) == mult_result )
<< std::endl;

and the error is:

ex_07-03.cpp:32: error: expected unqualified-id before '(' token
what now ?

Aug 9 '07 #7

P: n/a
arnuld wrote:
>On Aug 9, 11:12 am, Ian Collins <ian-n...@hotmail.comwrote:
>No, just use what I wrote.


i did use that, now i just modified it to:

std::cout << std::assert( raise_power(i, j) == mult_result )
<< std::endl;

and the error is:

ex_07-03.cpp:32: error: expected unqualified-id before '(' token
Don't output it, just use the assert to validate your test. If the
assertion fails, your program will abort with an error message.

--
Ian Collins.
Aug 9 '07 #8

P: n/a
On Aug 9, 11:59 am, arnuld <geek.arn...@gmail.comwrote:
i did use that, now i just modified it to:

std::cout << std::assert( raise_power(i, j) == mult_result )
<< std::endl;

and the error is:

ex_07-03.cpp:32: error: expected unqualified-id before '(' token

what now ?
ok i got it. "assert" is a preprocessor-macro that does not return
anything and hence causes conflict with the overloaded operator "<<"

but then i have to write more-code:

assert( raise_power(i, j) == mult_result );
std::cout << ( raise_power(i, j) == mult_result ) << std::endl;

but then, is writing more code a good idea ? (when i know that
expression works fine)

Aug 9 '07 #9

P: n/a
arnuld wrote:
On Aug 9, 11:59 am, arnuld <geek.arn...@gmail.comwrote:
>i did use that, now i just modified it to:

std::cout << std::assert( raise_power(i, j) == mult_result )
<< std::endl;

and the error is:

ex_07-03.cpp:32: error: expected unqualified-id before '(' token

what now ?

ok i got it. "assert" is a preprocessor-macro that does not return
anything and hence causes conflict with the overloaded operator "<<"

but then i have to write more-code:

assert( raise_power(i, j) == mult_result );
std::cout << ( raise_power(i, j) == mult_result ) << std::endl;

but then, is writing more code a good idea ? (when i know that
expression works fine)
No, the point was if your test passes, the program exits cleanly, if it
fails it aborts and you get an error message.

you could just write

assert( raise_power(i, j) == mult_result );
std::cout << "OK" << std::endl;

You can add more assertions,

assert( raise_power(2, 2) == 4 );

and so on.

I had assumed your book would have covered assert!

--
Ian Collins.
Aug 9 '07 #10

P: n/a
arnuld wrote:
On Aug 9, 11:59 am, arnuld <geek.arn...@gmail.comwrote:
>i did use that, now i just modified it to:

std::cout << std::assert( raise_power(i, j) == mult_result )
<< std::endl;

and the error is:

ex_07-03.cpp:32: error: expected unqualified-id before '(' token

what now ?

ok i got it. "assert" is a preprocessor-macro that does not return
anything and hence causes conflict with the overloaded operator "<<"
Sorry to have distracted you with this, the more interesting problem to
solve and test is supporting negative numbers! Let's see how you get on
with those...

--
Ian Collins.
Aug 9 '07 #11

P: n/a
On Aug 9, 9:38 am, Ian Collins <ian-n...@hotmail.comwrote:
arnuld wrote:
Sorry to have distracted you with this, the more interesting problem to
solve and test is supporting negative numbers!
Especially for a function which returns an int. (But it
probably shouldn't, because of the risk of overflow.)

Note too that handling negatives intelligently is definitly
non-trivial. You can't just do something like:

double
power( int i, int n )
{
double r = 1.0 ;
double m = i ;
bool invert = n < 0 ;
if ( invert ) {
n = -n ;
}
while ( n 0 ) {
r *= m ;
m *= m ;
n >>= 1 ;
}
return invert ? 1.0 / r : r ;
}

-n might still be negative. (Formally, you'd have undefined
behavior in that case, but in practice, on the usual machines,
it's a no-op.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Aug 9 '07 #12

P: n/a
On Aug 9, 7:43 pm, James Kanze <james.ka...@gmail.comwrote:
Especially for a function which returns an int. (But it
probably shouldn't, because of the risk of overflow.)
hmm.. that is why you used double return type.

Note too that handling negatives intelligently is definitly
non-trivial. You can't just do something like:

double
power( int i, int n )
{
double r = 1.0 ;
double m = i ;
bool invert = n < 0 ;
if ( invert ) {
n = -n ;
}
while ( n 0 ) {
r *= m ;
m *= m ;
n >>= 1 ;
}
return invert ? 1.0 / r : r ;
}
your programme works fine both with +ve and -ve numbers but i do not
understand the meaning of "n >>= 1". you are shifting bits one by one
but what exactly will be the value of "n" after shifting one bit
right ? i am not able to know the value of "n". yes, it works but what
happens to the vale of "n" each time ?
to understand that i used this code:
#include <iostream>

int main()
{
int x = 3;

std::cout << "x: " << x << "\n\n";

while(x 0)
{
std::cout << "x: "
<< (x >>= 1)
<< std::endl;
}

return 0;
}

====== OUTPUT ==========
/home/arnuld/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra
test.cpp
/home/arnuld/programming/cpp $ ./a.out
x: 3

x: 1
x: 0
/home/arnuld/programming/cpp $

comparing it with your solution i do not understand anything at all.
-n might still be negative. (Formally, you'd have undefined
behavior in that case, but in practice, on the usual machines,
it's a no-op.)

--
James Kanze (GABI Software) email:james.ka...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
you said "n = -n" in if clause, so how can "n" still be a -ve number ?

Aug 10 '07 #13

P: n/a
Hi!

arnuld schrieb:
your programme works fine both with +ve and -ve numbers but i do not
understand the meaning of "n >>= 1". you are shifting bits one by one
but what exactly will be the value of "n" after shifting one bit
right ? i am not able to know the value of "n". yes, it works but what
happens to the vale of "n" each time ?
What happens if you shift "82341" one digit right? It is "8234" which is
a tenth of "82341". What happens if you shift a binary number one bit
right? It gets divided by two.
"n >>= 1" is equivalent to "n /= 2" but maybe faster
(propably not faster because the optimizer will generate identical code
for both).

What I don't understand is why the dopped bit is not looked at in each
iteration. I thought of:

while(n>0)
{
if( n & 1 )
r *= m;
m *= m;
n >>= 1;
}
you said "n = -n" in if clause, so how can "n" still be a -ve number ?
There is a negative int number "n" such that "-n" is too large to be
represented. It happens to usually come out as n again. That is "n ==
-n" is true (technically it is still undefined behaviour as James
already said).

Magic? No. Just take the least int number available:
std::numeric_limits<int>::min(). This is usually 0x80000000. To invert
it (according to 2-complements representation which is common) you need
to first flip all bits and then add 1:
0x80000000
flip: 0x7fffffff
add 1: 0x80000000
Same as before. Notice that 0x7fffffff is
std::numeric_limits<int>::max(). So adding 1 will overflow.

In short: there are usually more negative than positive numbers in the
domain of "int".

Frank
Aug 10 '07 #14

P: n/a
On Aug 9, 12:38 pm, Ian Collins <ian-n...@hotmail.comwrote:
Sorry to have distracted you with this, the more interesting problem to
solve and test is supporting negative numbers! Let's see how you get on
with those...
that is not distraction, it is a good exercise to. i used simple
logic to come up with my new code:

2 ^ 3 = 8
2 ^ -3 == 1/8 == 0.125

so i can use the same code and i only need to add something like "if
(y < 0) then (1/mult)". here is it and it works. BTW, thanks for the
simple but mind-bending exercise :)
/* C++ Primer - 4/e
*
* exercise 7.3
* STATEMENT
* write a programme to take two int paramaters and generate the
result of raising
* the first to the power of the second. write a programme to call
your function passing
* it two ints. verify the result.
*
*/

#include <iostream>
#include <cassert>

/* raises "x" to the power "y" */
double raise_power(int x, int y)
{
double mult = 1.0;
double temp = y;
/* if y < 0 then make it positive */
if( y < 0)
{
y = -y;
}

while( y-- )
{
mult = mult * x;
}

return ( temp < 0 ) ? (1.0 / mult) : mult;
}
int main()
{
int i = 2;
int j = -3;

std::cout << ( raise_power( i, j ) ) << std::endl;

return 0;
}

Aug 10 '07 #15

P: n/a
arnuld wrote:
>On Aug 9, 12:38 pm, Ian Collins <ian-n...@hotmail.comwrote:
>Sorry to have distracted you with this, the more interesting problem
to solve and test is supporting negative numbers! Let's see how you
get on with those...

that is not distraction, it is a good exercise to. i used simple
logic to come up with my new code:

2 ^ 3 = 8
2 ^ -3 == 1/8 == 0.125

so i can use the same code and i only need to add something like "if
(y < 0) then (1/mult)". here is it and it works. BTW, thanks for the
simple but mind-bending exercise :)
/* C++ Primer - 4/e
*
* exercise 7.3
* STATEMENT
* write a programme to take two int paramaters and generate the
result of raising
* the first to the power of the second. write a programme to call
your function passing
* it two ints. verify the result.
*
*/

#include <iostream>
#include <cassert>

/* raises "x" to the power "y" */
double raise_power(int x, int y)
{
double mult = 1.0;
double temp = y;
'temp' doesn't need to be "double". An 'int' will do.
/* if y < 0 then make it positive */
if( y < 0)
{
y = -y;
}

while( y-- )
{
mult = mult * x;
}

return ( temp < 0 ) ? (1.0 / mult) : mult;
}

[..]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 10 '07 #16

P: n/a
On Aug 10, 12:57 pm, Frank Birbacher <bloodymir.c...@gmx.netwrote:

[...]
What I don't understand is why the dopped bit is not looked at in each
iteration. I thought of:
while(n>0)
{
if( n & 1 )
r *= m;
m *= m;
n >>= 1;
}
Because I typed the code in too fast, and only tested it with
some simple values for which it happened to work.
you said "n = -n" in if clause, so how can "n" still be a -ve number ?
There is a negative int number "n" such that "-n" is too large to be
represented. It happens to usually come out as n again. That is "n ==
-n" is true (technically it is still undefined behaviour as James
already said).
And of course, it depends on the implementation. It's only a
problem on machines using 2's complement---it works fine with
1's complement and signed magnitude. Of course, off hand, I
only know of one, relatively exotic mainframe that uses 1's
complement today, and as far as I know, the last signed
magnitude machine went out of production some years ago. So
it's probably a safe bet that the machine he's programming on
uses 2's complement.

--
James Kanze (GABI Software) email:james.ka...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Aug 11 '07 #17

P: n/a
On Aug 10, 2:40 pm, arnuld <geek.arn...@gmail.comwrote:

[...]
/* raises "x" to the power "y" */
double raise_power(int x, int y)
{
double mult = 1.0;
double temp = y;
/* if y < 0 then make it positive */
if( y < 0)
{
y = -y;
}
while( y-- )
{
mult = mult * x;
}
return ( temp < 0 ) ? (1.0 / mult) : mult;
}
I tried it with 5, -2147483648. The result was 1. Somehow, I
don't think that's right.

--
James Kanze (GABI Software) email:james.ka...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Aug 11 '07 #18

P: n/a
On Aug 11, 5:30 pm, James Kanze <james.ka...@gmail.comwrote:
I tried it with 5, -2147483648. The result was 1. Somehow, I
don't think that's right.
i think, -2147483648 is too big to fit in a double.

then you can also use these arguments:

-343458234892348914789789,
78923489702347890123468923423234234784234234789412 3478247812378

but why i need such big values ? may be they are specific
requirements for some specific domain like scientific
programming, ....... why do i even need -2147483648 ?

i think just making it work for values which fit in a double is ok.

Aug 11 '07 #19

P: n/a

arnuld <ge*********@gmail.comwrote in message
news:11**********************@q4g2000prc.googlegro ups.com...
On Aug 11, 5:30 pm, James Kanze <james.ka...@gmail.comwrote:
I tried it with 5, -2147483648. The result was 1. Somehow, I
don't think that's right.

i think, -2147483648 is too big to fit in a double.
WHAT?

int big( -2147483648 ); // int is 32bit on my machine
cout<<" big="<<big<<std::endl;
// out: big=-2147483648
// include <limits>

std::cout<<" dbl min() ="
<< std::numeric_limits<double>::min()<<std::endl;

std::cout<<" dbl max() ="
<< std::numeric_limits<double>::max()<<std::endl;

std::cout <<" dbl digits ="
<<(std::numeric_limits<double>::digits)<<std::endl ;

std::cout<<" LD digits ="
<<(std::numeric_limits<long double>::digits)<<std::endl;

/* - output - (on my machine)
dbl min() =0.000000 // note: only precision(6)
dbl max() =1.79769e+308
dbl digits =53 // 'digits' is num of bits
LD digits =64
*/

Compare those 'digits' with int, long, long long(if you have it) digits.

When you are not sure, test it.

--
Bob R
POVrookie
Aug 11 '07 #20

P: n/a
On Aug 11, 6:49 pm, arnuld <geek.arn...@gmail.comwrote:
On Aug 11, 5:30 pm, James Kanze <james.ka...@gmail.comwrote:
I tried it with 5, -2147483648. The result was 1. Somehow, I
don't think that's right.
i think, -2147483648 is too big to fit in a double.
Are you kidding. On most machines today, a double will handle
anything up to around 1e306, with 17 digits precision.

In my version, the arguments were int, and the above value fits
into an int on all of the machines I currently work on; it is
guaranteed (by the standard) to fit into a long or a double.
then you can also use these arguments:
-343458234892348914789789,
78923489702347890123468923423234234784234234789412 3478247812378
but why i need such big values ? may be they are specific
requirements for some specific domain like scientific
programming, ....... why do i even need -2147483648 ?
I don't know? But you do want it to work with all legal values.

In fact, of course, I just raised the point because someone
mentionned accepting negative values. Your orginal code was
probably all the book was looking for, but at some point, you
will have to learn the awkward particularity that on most
machines, the absolute value of the most negative value of an
integral type will not fit in that integral type. Which means
that you often have to pay a little extra attention.
i think just making it work for values which fit in a double is ok.
-2147483648 definitly fits into a double. With no loss of
precision on most machines.

--
James Kanze (GABI Software) email:james.ka...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Aug 11 '07 #21

This discussion thread is closed

Replies have been disabled for this discussion.