 Feature Articles
 CodeSOD
 Error'd
 Forums

Other Articles
 Random Article
 Other Series
 Alex's Soapbox
 Announcements
 Best of…
 Best of Email
 Best of the Sidebar
 Bring Your Own Code
 Coded Smorgasbord
 Mandatory Fun Day
 Off Topic
 Representative Line
 News Roundup
 Editor's Soapbox
 Software on the Rocks
 Souvenir Potpourri
 Sponsor Post
 Tales from the Interview
 The Daily WTF: Live
 Virtudyne
Admin
Admin
I like the way it will round 1450 up to 2000 :)
Admin
Alot of people don't realize there's more than one kind of rounding. This appears to be similar to roundtonearesteven (RNE). There are statistical reasons why you don't always want to round up if the leastsignificant digit is >= 5, and down otherwise. I've had to implement similar schemes in hardware. Of course there, I wasn't parsing a string, and I was able to reduce the rounding logic to a 3stage bitwise logic operation.
Admin
private int CalculateGap(int min, int max, int interval)
{
int gap = (max  min) / interval;
int digits = (int)Math.Log10(gap);
double roundingFactor = Math.Pow(10, digits);
return (int)(Math.Round(gap / roundingFactor) * roundingFactor);
}
Admin
No, I don't think this is 'round half even'. It's round 4550ths up.
And implemented in a completely asinine way.
Admin
Nice solution! Although string manipulation is more efficient...(just kidding)[:P]
Admin
Oops, this is better :)
private int CalculateGap(int min, int max, int interval)
{
int gap = (max  min) / interval;
return (int)Math.Round(gap, 0);
}
Admin
Personally I'd be happier with...
gap % 10 (gap / 10) % 10 (gap / 10 / 10) % 10 (gap / 10 / 10 / 10) % 10
And so on.
Admin
I've seen a lot of stringnumber handling problems in inexperienced programmers, especially among the managed languages crowd. I think part of the problem lies in the academics at colleges. Scenarios like this one, which are the breadandbutter of any normal programming job, are usually glossed over because they tend to be languagespecific (e.g., math libraries, string handling classes, etc.). Take any kind of data structures classes and they'll spend weeks and weeks going over the abstract stuff like sorting algorithms and bigO notation while spending relatively little time teaching the things that matter in the real world.
Anyway, just an observation from someone who attended CS classes at 3 different universities.
Admin
True; But you're supposed to learn the general/abstract stuff at school.
You're not going to learn about Kruskal and Prim at your first job.
That being said, A programmer in their Junior year should of already done enough projects to build up the experience to handle a problem like this correctly.
Unless they had the exchange student that sits in the front row do all their projects :)
Admin
Seeing how the author didn't check for numbers with 4 or more digits, I don't think he ever had to worry about that scenario.
Admin
My above comment was in response to crlf's comment.
I thought the forum software was going to put the quote in for me. Guess I was wrong.
Admin
Here's a solution to a similar "ygap" problem that I wrote. It's meant to nearly replicate the way excel autoscales axes in a graph. It attempts to find the "ideal" spacing of 510 divisions on axes, given a min and a max. You may notice one possible WTF in that I used with CString.Format() to round. That's because MFC's math library only has ceil(), floor(), and binary mantissa functions, no "true" rounding functions.
Feel free to tear it apart and make fun of me at your leisure.
Note that much of the class has been snipped. The proverbial meat without potatoes. Huh, apparently I never wrote comments. Have fun!
void CGraphScale::SetMinMax(double dMin, double dMax)
{
m_dActualMin = dMin;
m_dActualMax = dMax;
int i, nMaxIter;
CString strTemp;
double dDiff = dMax  dMin;
if(dDiff>1)
{
strTemp.Format("%.0f",ceil(dDiff));
nMaxIter = strTemp.GetLength();
strTemp = "1";
for(i=0; i<nmaxiter ;="" i="">
strTemp.AppendChar('0');
m_dSpacing = atol(strTemp);
}
else if(dDiff>1e16)
{
m_dSpacing = 1;
}
else
{
AfxMessageBox("Error: dMax must be greater than dMin.");
ASSERT(true);
return;
}
double dLabel, dMinLabel;
for(m_nDivisions = 0; m_nDivisions<5;)
{
strTemp.Format("%.1e", m_dSpacing);
switch(strTemp.GetAt(0))
{
case '1':
case '5':
m_dSpacing/=2;
break;
case '2':
m_dSpacing/=2.5;
break;
}
if(dMin>=0)
{
for(dLabel = 0; dLabel < dMin; dLabel+=m_dSpacing);
if(dLabel!=dMin)
dMinLabel = dLabelm_dSpacing;
else
dMinLabel = dLabel;
}
else
{
for(dLabel = 0; dLabel > dMin; dLabel=m_dSpacing);
dMinLabel = dLabel;
}
m_nDivisions = dDiff / m_dSpacing;
for(dLabel = dMinLabel + m_nDivisions * m_dSpacing;
dLabel<dmax ;="">
dLabel+=m_dSpacing, m_nDivisions++);
}
m_aTickMarks.SetSize(m_nDivisions+1);
for(dLabel=dMinLabel, i=0; i<=m_nDivisions; dLabel+=m_dSpacing, i++)
{
if(abs(dLabel)<1e16) dLabel = 0;
m_aTickMarks[i]=dLabel;
}
}
</dmax></nmaxiter>
Admin
Still, it will round 145 up to 200 nevertheless.
Admin
I originally tried to use a simple formula with log, but it wasn't always accurate due to rounding. The following Java code runs about 10 times faster than the original (when translated into Java):
Admin
Admin
If I'm not mistaken, it will work for 'any' length number. It's only checking the first three digits because that's how rounding works (usually you only look at the first two but anyway.)
Admin
Fred Flintstone, what was the rounding problem? Would the following not work?
private int calculateGap(int min, int max, int interval)
{
int gap = (max  min) / interval;
int digits = (int)(Math.log(gap) / Math.log(10));
double roundingFactor = Math.pow(10, digits);
return (int)(Math.round(gap / roundingFactor) * roundingFactor);
}
Admin
PointF[] ChartData(string funct, int xmin, int xmax, int npts) {
PointF[] pts = new PointF[npts];
float step = (xmaxxmin)/(float)(npts1);
for(int j = 0; j < npts; j++) {
pts[j].X = (float)(xmin + step*j);
pts[j].Y = (float)(Expression.expression.Evalute(funct, new string[]{"x"}, new double[]{pts[j].X}));
}
return pts;
}
Admin
Actually, it's even more absurd than most of the respondents realize. Why? Because a close look at the code shows that it is in C#, and (as one of the anonymous poster showed) the standard C#.Net Math.Round() method takes a precision argument.
Admin
I see three optimizations here:
1. The function takes min, max, and interval arguments. This saves on one of those expensive floating point subtraction operations.
2. Hand coded loop unrolling in assigning the digit variables. Sometimes "for" loops are just too slow.
3. The variable "result" is declared near the top of the function and initialized to zero. Then, at the bottom, it is assigned a value, and immediately returned. Because if he had returned the expression "firstDigit * (int)Math.Pow(10, length  1)" directly, it would take up a lot more space on the stack.
You're all just jealous because this guy is a l33t h4X0r and you're not.
Admin
You sure?
It doesnt reevaluate secondnumber, so secondnumber will still be 4 so it will not be >=5.
Rounds 145 to 155 (which is odd in itself mind).
Admin
That would not do the same thing as the WTF code, so without the spec we have no way of knowing whether it would be a better or worse solution. If the spec says that numbers between 145 and 150 should be rounded up to 200, then Math.Round() would not be adequate. Stick to removing the WTFness of the actual code rather than solving a different, slightly simpler problem.
I'm not saying that the WTF code can't be simplified, but that doesn't mean we should jump to using the simplest thing we can think of whether or not it actually does what it's supposed to. We don't know exactly how the code was supposed to behave, and we could guess that the x45 thing was a bug, but it might actually be a requirement, and the very reason the programmer chose to implement it this way instead of using Math.Round()
Admin
Now, you're wrong too. In the end, 145 will be round up to 200 because he first evaluates the third digit, then the second one.
Start with 145.
firstDigit > 1
secondDigit > 4
thirdDigit > 5
Since thirdDigit >= 5, secondDigit > SecondDigit + 1 > secondDigit > 5
Then secondDigit >= 5, firstDigit > firstDigit + 1 > firstDigit > 5
Finally, result > firstDigit x 100 > 200.
However, keep in mind that 14567890 will also be rounded to 20000000 because it starts with 145.
One fun thing though... What would happen if Max < Min? [:D] Or worse, when Max equals Min? [:D] Okay, we all know whe should not return 0 as Interval but what if we give a negative Interval?
Admin
You might scream WTF at this solution but it's guaranteed to work in Microsoft Visual Studio C++:
Laziest solution to rounding a number:
double dSomeNumber = 1.2345;
CString strTemp;
//Rounding to two significant digits
strTemp.Format("%.1e", dSomeNumber);
dSomeNumber = atof(strTemp);
Change the number between . and e to change the digits of precision.
Bingo.
My lengthier post above this one uses a similar technique that creates an object (containing an array of numbers) that mimics Excel's way of autoformatting the labels on an axis. I will give the full .h and .cpp if somebody replies.
Admin
Morover, the reason why the long code I posted is longer than everybody else's is because it takes into consideration many error situations:
One way to improve my code would be to add an extra argument for a target number of intervals. Right now it assumes that mere mortals can only handle between 5 and 10 intervals, and chooses the best number of intervals to fit the data.
Admin
In response to SchooolReLea's post, the code is written in Java, not C#. I guess that won't matter though.
Admin
The original code would round 145 up to 200 (1450>2000, 14500>20000, etc.). This solution does not.
Admin
In theory, this should work:
The problem is that when it should get a value of 2, it gets 1.999999999. You can fudge it by adding 0.5500000001, but that's kinda ugly. Besides, the pow and log functions are quite a bit slower. Ignoring the fact that your original algorithm didn't handle values like 145 correctly, it is still about 10 times slower than the iterative solution I posted. The above is about 1.5 times slower than your solution, but does handle 145 correctly.
Admin
At my last job our client was actually requesting this mode of rounding. We were still trying to talk them out of it when I left.
In any event, it's still not neccesary to convert to Stings to acomplish this. You can do it in a number of ways, including (but not limited to) doing two half up rounds. If I were to rewrite this (and wasn't concernd with floating point errors) and was pretty sure it was a one time need, I'd probably do something like:
double temp = rawGap;
while (temp >= 100) temp = temp / 10;
temp = Math.round(temp);
temp = temp / 10;
temp = Math.round(temp);
Which isn't neccesarily more performant than the original, but it's a lot easier to understand IMO.
Admin
Here's the ful solution of the above. I think it works, but only if raw gap >= 1 , of course. The original solution would also fail for numbers smaller than 1, I believe.
double temp = rawGap;
int size = 0;
while (temp >= 100) {
i++;
temp = temp / 10;
}
temp = Math.round(temp);
if (temp >= 10) {
i++;
temp = temp / 10;
}
temp = Math.round(temp);
return temp * Math.pow(10, i);
Admin
If it is, then the coder must have been studying C# at the time he/she wrote it and got confused, because there are at least three things I can see here that would be wrong if it were Java code:
Admin
So, that routine will round up 045 to 100!
thats rubbish!
Admin
Rubbish? Yep, but it is the functionality that the original programmer wanted to have, apparantly, with his WTF code. Yes, it seems crazy and perhaps it is even crazy but it wouldn't suprise me that this has even been part of the original design! [:)]
Admin
Try floor( x + 0.5 ), if there's no round() function.
Forgive me, but I didn't look at the code to see if you needed nearesteven behavior, or some other atypical rounding.
Admin
public String getPaula(int toRound) { String paula = "brillant";
}
Admin
Assuming that gap cannot be negative, this function is equivalent:
I am not actually sure what the original code would do for a negative gap. I assume that it would crash on the hyphen character here:
firstDigit = int.Parse(gapString.Substring(0, 1));