|
Yeah, I switched a and c to better resemble the OP; and of course I forgot one instance.
I'll fix it!
BTW: you don't want to know what else my log() method is capable of...
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
Luc Pattyn wrote: where epsilon would be a small positive constant, say 1.0E-15
Or even Double.Epsilon - thats why it's there.
|
|
|
|
|
I don't think so; MSDN says "The value of this constant is 4.94065645841247e-324.", as it is the smallest non-zero value a double can hold.
However what the OP probably needed is the smallest value you can add to one to make it different from one (that is about 1.E-15), or even a multiple thereof, as testing against the smallest possible value would be risky itself, as a lot of floating-point operations aren't accurate up to the last bit.
IMO they should not have called their value Epsilon.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
Luc Pattyn wrote: where epsilon would be a small positive constant, say 1.0E-15
You can't reliably use a constant for comparisons. The value of epsilon has to be related to the magnitude of the numbers involved. For example (VC++ 6 compiler for reference)
double d1 = 1e299;
double d2 = 1e299 - 1;
double diff = d1 - d2;
gives a result with diff being zero, not one.
double d1 = 1e10;
double d2 = 1e10 - 1;
double diff = d1 - d;
gives a result with diff being 1, as expected.
Basically, epsilion has to be larger than the minimum precision of the double data type given the values contained in it, and the precision, as an absolute, varies with the values.
|
|
|
|
|
that is elementary.
the example was about a value of 1, that is why 1.E-15 was appropriate.
In general, for a non-zero positive target value, one would typically use:
if (Math.Abs(currentValue-targetValue) < targetValue*epsilon) ...
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
It might be obvious to you, but the "absolute value of difference less than very small constant" idiom is very common, and leads to some really hard to find bugs.
I only mentioned it because your original post used the constant, and the more that gets published, the more the bug hets promuglated in code all over the place. You even see it in CS academic texts, which is really concerning.
|
|
|
|
|
Luc Pattyn wrote: In general, for a non-zero positive target value, one would typically use:
The minimum amount of error one should accept would depend not on the target value, but upon the magnitude of the largest value from which something was subtracted to yield the target value. For example, when subtracting 281474976710655.1 from 281474976710656.1, the final result will be about 1.03125 which is much larger than a typical 'epsilon' one would expect for a number around one.
The real question, of course, should be how close does the number need to be to be identical from a 'practical' perspective. That's going to depend entirely on the application. If one is trying to produce a list of boards one needs to cut, and two boards differ by 0.1", that may or may not be a difference worthy of producing a separate line item. If boards have to fit within 0.05", the 0.1" difference would be significant. If the boards are going to have some mounting slop, even a 0.5" difference might be insignificant. Obviously the computer isn't going to magically know what's meaningful and what isn't.
|
|
|
|
|
At the A.ToString() part.
|
|
|
|
|
That code makes me sad
cheers,
Chris Maunder
The Code Project | Co-founder
Microsoft C++ MVP
|
|
|
|
|
This little gem is used to construct the where condition for an SQL query that selects all coordinates within a certain distance from a point (in a PHP app). The coordinates are stored in the db in a single field, where the lat and lon are separated by a comma. The SQL is splitting on that and running a whole bunch of calculations. The table can be millions of entries big. I kid you not.
$distance = "ROUND(((ACOS( SIN({$latitude} * PI()/180 ) * SIN(SUBSTRING_INDEX({$tablename}.{$fieldname}, ',',1) * PI()/180 ) + COS({$latitude} * PI()/180 ) * COS(SUBSTRING_INDEX({$tablename}.{$fieldname}, ',',1) * PI()/180 ) * COS(({$longitude} - SUBSTRING_INDEX({$tablename}.{$fieldname}, ',',-1)) * PI()/180))*180/PI())*60*1.1515),6)";
$where = "{$distance} <= " . $dbs->addQuotes( "5" );
|
|
|
|
|
It's probably immaterial, but what does the constant 1.1515 represent in the equation?
The great thing about generated SQL is that you never have to maintain the SQL. The horror about generated SQL is that you have to maintain the generator.
Chris Meech
I am Canadian. [heard in a local bar]
In theory there is no difference between theory and practice. In practice there is. [Yogi Berra]
|
|
|
|
|
Somebody manually wrote this, not auto generated...
|
|
|
|
|
Chris Meech wrote:
It's probably immaterial, but what does the constant 1.1515 represent in the equation? Confused
Its the distance of one nautical mile.
|
|
|
|
|
Thanks. It was a constant that didn't ring any bells for me. Now that I know it's for nautical miles, it will be a ship's bell that should go off next time.
Chris Meech
I am Canadian. [heard in a local bar]
In theory there is no difference between theory and practice. In practice there is. [Yogi Berra]
|
|
|
|
|
elchupathingy wrote: Its the distance of one nautical mile
In case anyone is wondering about the relevance of a nautical mile, it's because a nautical mile is defined as one minute of arc around the Earth's circumference. So this calculation is converting minutes of arc into miles.
According to a quick search around the interweb, a nautical mile is actually defined as 1.1508 miles, not 1.1515. So for large distances, this calculation is going to be slightly off. If you sail half way round the world, you'll be 8 miles away from where you think you are with this calculation.
|
|
|
|
|
While we're all dragging out our ocean navigation knowledge...
David Skelly wrote: a nautical mile is defined as one minute of arc around the Earth's circumference
It's worth highlighting that this works at the equator and along meridians, but is not accurate if you are traveling east/west along say 45 degrees north lattitude.
Another reason this calculation probably isn't going to be accurate is that the shortest distance between two points is an arc. The further you get from the equator the more curve there is in that arc.
Of course if they are just trying to locate stores within 50 miles of your location, their math is probably good enough...
|
|
|
|
|
It's actually not 1.1515, but 60*1.1515, i.e. 69.09. One degree corresponds to 69.09 miles (non-nautical).
I found that out by doing the maths behind that formula. He converts lots of degree-coordinates into radian-coordinates by that *PI/180, then calculates the shortest distance along a great circle in radians (that's the spherical geometry equivalent of the Pythagoras formula for orthogonal triangles), converts that back to degrees along that circle, and then transforms that to miles; for kilometers use 111.1.
Nonetheless, I do not understand why he uses 60*1.1515 instead of 69.09.
|
|
|
|
|
A full circle means 360 degrees or 2*PI radians. Consequently, I would suggest the original programmer replace all PI()/180 by 2*PI()/360 . That makes things much easier to understand!
|
|
|
|
|
The ugliest part is database structure.
The coordinates are stored in the db in a single field, where the lat and lon are separated by a comma
I would TALK to the programmer, but I would FIRE the database architect immediately.
I did similar thing (if distances you deal with are not that big, you can do it without acos and sin, and even without SQRT in SQL code if you calculate distance*distance before you run the query). Yet it works horribly slow. I made it run very fast by indexing lat and long and finding all locations within the lat,long square, then cutting off everything outside of a circle...
Now you see why I suggest to fire the database architect. You cannot use index on lat, long, so any code you write is doomed to work sluggish.
|
|
|
|
|
for( int i = 1 ; i <= 3 ; i++)
{
if(i==1){…}
else if(i==2){…}
else if(i==3){…}
else{…}
}
source: http://www.coding-horror.de/?p=258
|
|
|
|
|
Unfortunately I've seen this sort of thing far too often.
It's up there with if((x == 1) && (x != 2)) and similar stuff.
Regards
David R
---------------------------------------------------------------
"Every program eventually becomes rococo, and then rubble." - Alan Perlis
The only valid measurement of code quality: WTFs/minute.
|
|
|
|
|
Some people really don't get when they should use switch/select statements
|
|
|
|
|
|
The fact that the final else block will never be executed suggests either (a) this code used to do something different and has been hacked around blindly, or (b) the person who wrote it didn't really understand what he was doing.
|
|
|
|
|
or (c) he really didn't trust integers. To be sure, to be sure, to be sure...
You should never use standby on an elephant. It always crashes when you lift the ears. - Mark Wallace
C/C++ (I dont see a huge difference between them, and the 'benefits' of C++ are questionable, who needs inheritance when you have copy and paste) - fat_boy
|
|
|
|