|
David Kentley wrote: It's possible that, as an optimization, "fixing" this has zero impact on real world performance while (slightly) obfuscating the code.
I'm pretty sure pow() only takes and returns doubles which means the original code is casting two ints in and one back out in addition to its internal pow goodness. I'm guessing the shift is a wee bit faster.
|
|
|
|
|
Robert Surtees wrote: I'm guessing the shift is a wee bit faster.
Which, as was argued here, is very probably of no importance, while the resulting obfuscation of the intent of the calculation is important.
Let's think the unthinkable, let's do the undoable, let's prepare to grapple with the ineffable itself, and see if we may not eff it after all. Douglas Adams, "Dirk Gently's Holistic Detective Agency"
|
|
|
|
|
jhwurmbach wrote: Robert Surtees wrote:
I'm guessing the shift is a wee bit faster.
Which, as was argued here, is very probably of no importance, while the resulting obfuscation of the intent of the calculation is important.
I'd say it's important. Gary's XT doesn't have an 8087 plugged in.
|
|
|
|
|
Based on what he was using this for (constructing a bit string), I would say using the pow() obscured the intent more than the shift operation did.
Software Zen: delete this;
|
|
|
|
|
Robert Surtees wrote: I'm pretty sure pow() only takes and returns doubles which means the original code is casting two ints in and one back out in addition to its internal pow goodness. I'm guessing the shift is a wee bit faster.
VC++ compiler is smart enough to implement it using shift instead of pow .
Anyway, IMHO shift syntax is far more clean.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
[my articles]
|
|
|
|
|
The original surrounding code looked something like this:
for (int i = 0; i < 16; i++) {
CString name;
name.Format(_T("Stuff_%d.dat"),(int)pow(2,i));
}; Thinking about it, if I wanted to maximize readability, I would have done this:
int name_value = 1;
for (int i = 0; i < 16; i++) {
CString name;
name.Format(_T("Stuff_%d.dat"),name_value);
name_value *= 2;
}; The only reason I found this is a compiler error in the original (int)pow(2,i) expression from VS2008 (ambiguous override).
Software Zen: delete this;
|
|
|
|
|
David Kentley wrote: Not that "2 << i" is that unreadable, but you get the idea.
In fact it isn't unreadable, it is wrong.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
[my articles]
|
|
|
|
|
Can you guarantee that floating point inaccuracies + truncation in the cast doesn't introduce a problem?
A quick check shows they don't on VC8, but I wouldn#t have bet on it.
Further, if your compiler uses the canonical (if simplistic) implementation of
double pow_simple(double x, double y) { return exp(y*log(x)); }
you fail pretty quickly with pow(2,3) = 7.9999999999999982
To add a pitfall to a lurking bug: if you use the default %f specifier for that, it dutifully prints 8.000000, but truncates it to 7 when casting to int.
Also, when using 64-bit integers, starting with pow(2,51) double loses on accuracy.
|
|
|
|
|
That is the first thing I thought of when I saw this. The thought of converting floating point to integers using casts keeps me awake at night.
I am actually currently working on a project at work that has a few of these. I just started here at the time I noticed them. For fun, I thought it would be neat to try compiling this project (which was developed in VC++ 6.0) with VC 2005, and VC 2005 choked on these instances. Good job to the compiler team on that one. It also choked on a few things that I thought VC++ 6.0 should have, such as assigning an int literal to a CString. A few more bonus points to the team there, although 6.0 definitely should have caught that.
Of the pow(int,int)s, at least one could've used the x *= 2 form, as it was in a loop, and the others the shift form. In the end, I decided not to touch any of them, because for all I know the truncation does mess things up but somebody spent a bunch of hours putting in "fixes" to work around this. The routines in question don't seem to have any bugs for now, but since a lot of the other ones do, I decided to focus my energy on those.
|
|
|
|
|
Gary Wheeler wrote: I replaced it with the following expression:
And in the process introduced a subtle bug
|
|
|
|
|
Good catch!
I assume you are referring to the different results when having i with values smaller than 0 and bigger than 31...
Robert
|
|
|
|
|
Just smaller than 0, but as he is casting to int 31 or above could be a problem too, not sure if C (which I assume this is) will create a 'long' or 'long long' or whatever they use from the shift. But the result of usage of negative numbers are clear undefined.
|
|
|
|
|
Actually not; see my reply above.
Software Zen: delete this;
|
|
|
|
|
The code got optimized for readability for the 'junior' programmers.
And it has the potential to get easily chanced to (int)pow(3,i).
I say this to defend your senior...
Greetings from Germany
|
|
|
|
|
KarstenK wrote: defend your senior...
Actually, I'm senior to the guy that wrote this. I just thought that the guy should have picked a better way to achieve the desired affect.
Software Zen: delete this;
|
|
|
|
|
Like:
<font color="Blue">int</font> pow<font color="DarkBlue">(</font><font color="Blue">int</font> i<font color="DarkBlue">,</font> <font color="Blue">int</font> j<font color="DarkBlue">)</font>
<font color="DarkBlue">{</font>
<font color="Blue">switch</font> <font color="DarkBlue">(</font>j<font color="DarkBlue">)</font>
<font color="Blue">case</font> <font color="Red">0</font><font color="DarkBlue">:</font> <font color="Blue">return</font> <font color="Red">1</font><font color="DarkBlue">;</font>
<font color="Blue">case</font> <font color="Red">1</font><font color="DarkBlue">:</font> <font color="Blue">return</font> i<font color="DarkBlue">;</font>
<font color="Blue">case</font> <font color="Red">2</font><font color="DarkBlue">:</font> <font color="Blue">return</font> i <font color="DarkBlue">*</font> i<font color="DarkBlue">;</font>
<font color="Blue">case</font> <font color="Red">3</font><font color="DarkBlue">:</font> <font color="Blue">return</font> i <font color="DarkBlue">*</font> i <font color="DarkBlue">*</font> i<font color="DarkBlue">;</font>
<font color="Blue">case</font> <font color="Red">4</font><font color="DarkBlue">:</font> <font color="Blue">return</font> i <font color="DarkBlue">*</font> i <font color="DarkBlue">*</font> i <font color="DarkBlue">*</font> i<font color="DarkBlue">;</font>
<font color="DarkBlue">.</font><font color="DarkBlue">.</font><font color="DarkBlue">.</font>
<font color="DarkBlue">}</font>
|
|
|
|
|
Nope.
You forgot break; statement. Oh pardon, you're senior!
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
[my articles]
|
|
|
|
|
|
<br />
int pow(int i, int j)<br />
{<br />
switch (j) {<br />
default: return 0;<br />
case 0: return 1;<br />
case 32: i *= i;<br />
case 31: i *= i;<br />
case 30: i *= i;<br />
...<br />
case 1: return i;<br />
}<br />
}<br />
....
ewwwww
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
|
|
(stack madness variant)
int imul(int i, int j)
{
if (j==0 ) return 0;
else return imul(i,j-1) + i;
}
int ipow(int i, int j)
{
if (j==0) return 1;
else return imul(ipow(i,j-1) , i);
}
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
[my articles]
|
|
|
|
|
Gary Wheeler wrote: This was in code written by a senior developer
When seniority approaches retirement...
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
[my articles]
|
|
|
|
|
Do you work for the same company as me? I've seen someone write code just like that -- to create a bitmask.
|
|
|
|
|
But... but... but... this ISN'T VB...
Is it possible to have bad code written by a senior developer in a non-VB language???
|
|
|
|
|
We senior developers are very resourceful!
I want to die like my Grandfather.
Peaceful, Sleeping.
Not screaming like his passengers.
|
|
|
|