views:

284

answers:

6

I'm an inspector at a machine shop. I have an html report generated by another inspector that has some problems I need to fix. This isn't the first time: I need something better than PowerShell and RegEx. (Fear not internet warriors, I know I shouldn't use RegEx for html. I'm using HtmlAgilityPack now.)

I'm aware there are a lot of similar discussions on SO and on the internet in general. I didn't find anything quite this specific. I can write some small experiment apps to test some of this (and I plan to) but, I want to have some idea of if it will be future safe before I implement all of it. Even though I'm not a programmer by trade I have a good grasp of the concepts we're talking about; Don't worry about talking over my head.

Over a series of transformations is it likely I will have more than .0001 error? What about .00001?
-If a report's alignment is off, I may need to rotate and translate it multiple times.
-I've only implemented rotation and translation at this time but, I plan on adding more transformations that may increase the number and complexity of operations.
-The integer component can go into the thousands.
-Our instruments are certified to .0001 typically. Normal significant digit rules for scientific measurements apply.

Will the overhead of Decimal and writing the trig functions manually be incredibly time consuming (edit: at runtime)?
-Typically a report has 100 to 100 points. Each point is actually 2 points: Nominal (as modeled) and Actual (as measured.)
-Easiest to test, but I want to know before implementing math functions for Decimal.

Side question:
I have a point class, Point3D, that holds x, y and z. Since each data point is two of these (the Nominal and Actual.) I then have a class, MeasuredPoint, with two Point3D instances. There has to be a better name than MeasuredPoint that isn't annoyingly long.

Oh yeah, this is C#/.Net. Thanks,

+3  A: 

If you need accuracy to be maintained over multiple operations then you really ought to consider using Decimal. While it may be okay for holding numbers for a short time, no IEEE754-backed float format can sustain its value indefinitely as the number of operations applied increases.

Ignacio Vazquez-Abrams
The FAA would certainly prefer accuracy. Most people that fly would also. I just wasn't sure double couldn't hold *enough* accuracy. It's probably better to be unreasonably accurate than reasonably inaccurate, though. Thanks.
Josiah
If I've understood the question correctly, this answer is wrong - Decimal values won't provide more accuracy than doubles.
Joe
Decimal has perfect accuracy. Its precision is 28 significant digits.
Jonathan Allen
I suppose then that I've confused it with the `Decimal` type found in Python, which is an arbitrary precision fixed point format.
Ignacio Vazquez-Abrams
My understanding was that Decimal would have more accuracy. If that's not true my entire question is faulty and I probably deserve a few down votes.
Josiah
There is a *huge* difference between "accuracy" and "precision". The .NET `decimal` type is a 128-bit base-10 floating point number with a 96-bit mantissa and a 31-bit base-10 exponent. The IEEE-754 double-precision type is a 64-bit base-2 floating point number with a 52-bit mantissa and an 11-bit base-2 exponent. No floating-point storage of *any* kind can maintain precision indefinitely as the number of operations applied increases. The only reason to use `decimal` is because its rounding error is more intuitive to humans, not because its rounding error is strictly less.
Daniel Pryden
I tried to use precision to refer to number of decimal places and accuracy to refer to how close a datatype's representation of a decimal value was to the actual decimal value. I don't need it to indefinitely hold perfect accuracy. I just need it to reasonably hold it to four or five decimal places.
Josiah
@Josiah: And, as I pointed out in my answer, if your measurements aren't intrinsically powers of ten (and anytime you're working with radians in trig functions, those values aren't powers of ten), a single-precision 32-bit float will have no trouble keeping four or five decimal places of precision.
Daniel Pryden
Sorry about that. I hadn't seen your answer Daniel.
Josiah
+1  A: 

Try looking for a library that would handle your needs. I stumbled across W3b.sine in a half-hearted search. I've definitely encountered others in the past.

John Fisher
There's a nice library here as well: http://www.codeproject.com/KB/recipes/fractiion.aspx
Chris Shouts
A: 

Floats and Doubles are fast approximations, that's it.

Apart from 0.0 and 1.0, you won't even get exact representations for most constants (0.1 for instance). So if you have to guarantee a certain precision, using floating point arithmetic is not an option.

But if the goal is to achieve a certain precision, give or take a bit, then double might do. Just watch out for Loss of significance.

SealedSun
+1  A: 

Since you are talking about rotations as well as translations, as well as trigonometry functions, it seems safe to assume the values you are talking about are not exact multiples of 0.0001.

Based on this assumption:

  • With decimals, you will be essentially be rounding to 0.0001 (or your chosen precision) after each step, and these rounding errors will cumulate.

  • Double values would generally be more accurate: you would store internally with all available precision, and round to four decimals when displaying results.

For example, as the result of a rotation or transformation, you want to move by a distance of 1/3 (0.333....). And you want to repeat this movement three times.

If you store the distances as decimal with four decimal places (0.3333), the sum will be 0.9999, an error of 0.0001.

If you store as doubles, you can achieve much higher precision, and as a bonus performance will be better.

Really decimals are usually only used for financial calculations, where results are need to be exactly rounded to a fixed number of base ten decimal places.

Joe
Why would I be rounding after each step? And they do start as multiples of 0.0001. They're output to four decimal places.
Josiah
Double values are never more accurate than decimals. Decimals store the exact value, doubles can only store powers of two.
Jonathan Allen
@Jonathan Allen: No, decimals can only store powers of ten. Why do you assume that a power of ten is "the exact value" and a power of two isn't?
Daniel Pryden
"Why would I be rounding after each step?" You are always implicitly rounding after each step to the available precision. But you're right that it doesn't have to be to 4 decimals, that was just my assumption based on my reading of your question. You can use the full 28 decimal places available for the decimal type, but this is still less than the maximum precision when using doubles.
Joe
"they do start as multiples of 0.0001" - but you can store them as doubles with more precision than this, and only round to four decimal places when formatting for output.
Joe
@Daniel, when was the last time you saw a measuring device or stepper motor that represented numbers in powers of two?
Jonathan Allen
Yeah. That's what I had intended. I would like it to remain accurate to .00001 so errors happen at (at least) 1/100th my specified precision of .0001.
Josiah
@Jonathan Allen: I guarantee that any measurement device will give you an answer that is along the lines of "0.12345, plus or minus 0.00001". So the value is not guaranteed to be "exact" to that number of decimal places. The precision or lack thereof in the binary representation is epsilon compared to the lack of precision in the actual measurement and the unit conversion. As I've pointed out several times in this thread, a 32-bit single-precision floating point variable has more than enough bits to preserve the five or six decimal places of precision required for this task.
Daniel Pryden
Exact in that if the device returns the values "0.10000" then the decimal type will store "0.00001", not "0.10000000149011612". That minor delta doesn't matter for one or two calculations, but it can certainly add up over time.
Jonathan Allen
A: 

Frankly, I think FLOAT was a wrong turn in data processing. Because people work in decimal, and output is always translated into decimal, float just causes continual problems. I used to use float when a variable could hold a wide range of values, as in from 1E-9 to 1E9 kind of range, and use integers with a fixed number of decimal places managed in code otherwise. These days with the Java BigDecimal class and similar functionality in other languages, there's almost no reason to use float. Perhaps in an environment where you are doing a lot of calculations and performance is an issue, you'd accept the rounding problems. I don't think I've used a float in a program in at least ten years.

Jay
You say: "output is always translated into decimal". That is not necessarily true. In image processing, for example, output is usually translated into color or intensity, and decimal precision gains you nothing and costs you considerable performance.
Daniel Pryden
Daniel: Isn't that example a bit of an edge case?
Josiah
@Josiah: It may be an edge case but it's the first valid example that came to mind. Here's another: I do a great deal of scientific programming, and in scientific calculations, an error term is usually expected (e.g. the answer isn't 0.999, it's 1.0 +/- 0.001). Using decimals for that kind of math actually tends to *increase* the actual error, since most decimal implementations will "snap" to powers of ten.
Daniel Pryden
I wouldn't say that's an edge case. There are lots of cases where accuracy just isn't that important.
Jonathan Allen
@Daniel: Okay, I'll buy that one. Personally the graphics work I've done that I recall, I always used integers, carefully arranging the order of operations when necessary so I don't have to work with fractions.
Jay
It occurs to me that graphics is a case where if a pixel is off by 1 position, or if the amount of green is 123 when it should have been 124, this probably doesn't matter. So I'll concede: graphics is a case where floats might be perfectly suitable. I'm sure there are others out there who have had other circumstances where they work too. But what I was trying to say was, we would have been better off if CPUs had built-in support for fast decimal processing rather than having to do it all with high-level code.
Jay
+3  A: 

Don't implement trig functions with Decimal! There's a reason why the standard library doesn't provide them, which is that if you're doing trig, Decimal doesn't provide any added benefit.

Since you're going to be working in radians anyway, your values are defined as multiples/ratios of PI, which isn't representable in any base system. Forcing the representation to base ten is more likely to increase than decrease error.

If precision (minimum error in ulps) is important for your application, then you must read What Every Computer Scientist Should Know About Floating-Point Arithmetic by David Goldberg. That article does a much better job explaining than I would.

The upshot however is that if your desired precision is only 5 decimal places, even a 32-bit float (IEEE-754 single-precision) is going to be plenty. A 64-bit double IEEE-754 double-precision will help you be more precise with your error term, but a 128-bit base-10 floating-point value is just performance-killing overkill, and almost certainly won't improve the precision of your results one iota.

Daniel Pryden
Switched. This is exactly what I wanted to know.
Josiah