5

I've had this problem on my mind the last few days, and I'm struggling to phrase my question. However, I think I've nailed what I want to know.

Why does c# accept the inaccuracy by using floating points to store data? And what's the benefit of using it over other methods?

For example, Math.Pow(Math.Sqrt(2),2) is not exact in c#. There are programming languages that can calculate it exactly (for example, Mathematica).

One argument I could think of is that calculating it exactly is a lot slower then just coping with the inaccuracy, but Mathematica & Matlab are used to calculate gigantic scientific problems, so I find it hard to believe those languages are really significantly slower than c#.

So why is it then?

PS: I'm sorry for spamming you with these questions, you've all been really helpful

Community
  • 1
  • 1
Timo Willemsen
  • 8,717
  • 9
  • 51
  • 82
  • MatLab runs in a Java sandbox. If you don't believe that MatLab is slower, try creating a real-time program in MatLab. Been there, done that, no fun... :-) – Martin Hennings Jan 05 '11 at 12:26
  • Okay, but Wolfram Mathematica then? I couldn't find benchmarks on the internet where it's compared to c# – Timo Willemsen Jan 05 '11 at 12:27
  • 1
    The [CAS](http://en.wikipedia.org/wiki/Computer_algebra_system) built into the TI-89 calculator that practically got me through college math courses beats the pants off of the mathematical functionality built into the .NET Framework, too. The fact is simply that they're designed for totally different usage cases. – Cody Gray - on strike Jan 05 '11 at 12:39
  • Yes indeed, CAS is what I was looking for. But isn't there a library that can implement that? – Timo Willemsen Jan 05 '11 at 12:40
  • 2
    Have you seen [Math.NET](http://www.mathdotnet.com/Default.aspx)? It's not quite as powerful as Mathematica, but it might do what you want. Otherwise, I get the feeling that C# is the wrong tool for the job. – Cody Gray - on strike Jan 05 '11 at 12:49

8 Answers8

32

Why does c# accept the inaccuracy by using floating points to store data?

"C#" doesn't accept the tradeoff of performance over accuracy; users do, or do not, accept that.

C# has three floating point types - float, double and decimal - because those three types meet the vast majority of the needs of real-world programmers.

float and double are good for "scientific" calculations where an answer that is correct to three or four decimal places is always close enough, because that's the precision that the original measurement came in with. Suppose you divide 10.00 by 3 and get 3.333333333333. Since the original measurement was probably accurate to only 0.01, the fact that the computed result is off by less than 0.0000000000004 is irrelevant. In scientific calculations, you're not representing known-to-be-exact quantities. Imprecision in the fifteenth decimal place is irrelevant if the original measurement value was only precise to the second decimal place.

This is of course not true of financial calculations. The operands to a financial calculation are usually precise to two decimal places and represent exact quantities. Decimal is good for "financial" calculations because decimal operation results are exact provided that all of the inputs and outputs can be represented exactly as decimals (and they are all in a reasonable range). Decimals still have rounding errors, of course, but the operations which are exact are precisely those that you are likely to want to be exact when doing financial calculations.

And what's the benefit of using it over other methods?

You should state what other methods you'd like to compare against. There are a great many different techniques for performing calculations on computers.

For example, Math.Pow(Math.Sqrt(2),2) is not exact in c#. There are programming languages that can calculate it exactly (for example, Mathematica).

Let's be clear on this point; Mathematica does not "calculate" root 2 exactly; the number is irrational, so it cannot be calculated exactly in any finite amount of storage. Instead, what mathematica does is it represents numbers as objects that describe how the number was produced. If you say "give me the square root of two", then Mathematica essentially allocates an object that means "the application of the square root operator to the exact number 2". If you then square that, it has special purpose logic that says "if you square something that was the square root of something else, give back the original value". Mathematica has objects that represent various special numbers as well, like pi or e, and a huge body of rules for how various manipulations of those numbers combine together.

Basically, it is a symbolic system; it manipulates numbers the same way people do when they do pencil-and-paper math. Most computer programs manipulate numbers like a calculator: perform the calculation immediately and round it off. If that is not acceptable then you should stick to a symbolic system.

One argument I could think of is that calculating it exactly is a lot slower then just coping with the inaccuracy, but Mathematica & Matlab are used to calculate gigantic scientific problems, so I find it hard to believe those languages are really significantly slower than c#.

It's not that they're slower, though multiplication of floating points really is incredibly fast on modern hardware. It's that the symbolic calculation engine is immensely complex. It encodes all the rules of basic mathematics, and there are a lot of those rules! C# is not intended to be a professional-grade symbolic computation engine, it's intended to be a general-purpose programming language.

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 1
    Plenty of scientific calculators "cheat" by keeping a couple extra digits behind the scenes and using them to round rather than displaying them. Consider Google, which happily gets [`Sqrt(2)**2`](http://www.google.com/search?q=sqrt%282%29%2A%2A2) correct...but what about [`sqrt(1.999999999)**2`](http://www.google.com/search?q=sqrt%281.999999999%29%2A%2A2)? – Brian Jan 05 '11 at 17:22
  • 2
    +1 I can't tell you how refreshing it is to see a programmer who actually understands and appreciates significant figures. But this is a thoroughly fantastic answer for so many reasons. – Cody Gray - on strike Jan 07 '11 at 16:25
  • @Cody: Glad you liked it. If you are interested in more articles exploring various interesting corners of floating point math see http://blogs.msdn.com/b/ericlippert/archive/tags/floating+point+arithmetic/ – Eric Lippert Jan 07 '11 at 16:49
  • While floats/doubles are often used for measured quantities that are only accurate to 3-4 decimal places, they're even more often used for quantities which will end up being rounded to a small number of places before being used or displayed. Many graphics routines, for example, use 'float' or 'double'. BTW, more interesting than the question of why floating-point is used is the question of why .net doesn't provide any convenient means of using the 8087 long double type. While hardware support for 8-byte double is better than the support for long double, the latter is better for some purposes. – supercat Jan 27 '11 at 03:12
  • @Brian Somebody @ Google saw this and fixed it. :-) – Stonetip Dec 31 '12 at 17:25
12

One word: performance. Floating point arithmetic is typically implemented on hardware and is many orders of magnitude faster than other approaches.

What's more your example of MATLAB is bogus. MATLAB uses double precision floating point arithmetic just like C#.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    +1 Not only performance, but the fact that the value-performance tradeoff just isn't worth it in 99% of cases. The only time you need the high levels of accuracy that your question assumes is if you're doing specialized math or engineering calculations. And there's already software for that. – Cody Gray - on strike Jan 05 '11 at 12:30
  • Okay I've removed the MATLAB example. I wasn't too sure, but mathematica can do it right? – Timo Willemsen Jan 05 '11 at 12:30
  • 3
    @Timo There's a difference between numerical and symbolic computation. Most real world engineering and scientific problems are best served by numerical algorithms and for them floating point arithmetic is best. This is essentially re-phrasing what @Cody Gray is saying. – David Heffernan Jan 05 '11 at 12:33
3

Why does c# accept the inaccuracy by using floating points to store data?

This way, floating point support can map to the way hardware supports floating points, that is - it's the more or less the only way of taking advantage of floating point operations in hardware, which is much faster than a software solution. The drawback is the hardware represents the floating points with a finite number of bits, which leads to inaccuracy (note that the inaccuracy is well defined).

Other ways of representing floating point values needs a software solution, it is significantly slower and require more space. "Anyone" can implement that with what's available in c#, including native floating point support for the available hardware would be quite hard for "anyone" if this wasn't already supported in the language/CLR.

nos
  • 223,662
  • 58
  • 417
  • 506
2

For most programming problems, the inaccuracy is not a problem and float (or double) data types are good enough. Many years ago, there wasn't such thing as "floating point values" and software had to store such values as two integers. And performance was an issue (not mentioning programming errors--and wtf scenarios--from custom made floating point calculation functions). Thus a convention was designed and soon after computers were equiped with FPUs.

Now, when to use the FPU for calculations or using other mathematical librairies/programs (such as Mathematica) depends on the problem. For example, calculating vertexes in a 3d environment prefers performance over precision. But accounting software is different. In that aspect, both problem differ; an accounting software will not need to calculate complex numbers millions of times per seconds :) (edit: or if it does, some very expensive hardware will probably be part of the equation too!)

If you know that you'll be doing Math.pow(Math.sqrt(2),2) then you should rethink the way you store both values (like recalculating them every time). This is not a problem with the programming language, but more a conceptual problem.

Yanick Rochon
  • 51,409
  • 25
  • 133
  • 214
0

C# and most of all other languages (except specific ones, like Matlab) store floating point numbers as fixed-size fields (6 or 8 bytes), which leads to inaccuracy.

Nickolay Olshevsky
  • 13,706
  • 1
  • 34
  • 48
  • I know that, but why does it use floating point numbers, if there are other ways. – Timo Willemsen Jan 05 '11 at 12:27
  • @Timo What other ways, if you're using fixed-size fields? The vast majority of computing, except for scientific computing, does not need infinite-precision and can accept some level of innacuracy. –  Jan 05 '11 at 12:28
  • Because of processing speed, and storage efficiency. That's the main reason. Most programs doesn't need accuracy in 10 symbols after dot. – Nickolay Olshevsky Jan 05 '11 at 12:31
  • I don't know how you can do it, but mathematica can calculate it exactly, and there are probably other languages that can do it too. – Timo Willemsen Jan 05 '11 at 12:31
  • Many programming languages provide exact floating points. The drawback is it requires more space and is slower. There's a reason every 3d game out there takes advantage of the hardware for floating point support, and not use their own software floating point library with exact precision. – nos Jan 05 '11 at 12:36
  • 1
    The sizes in common use are IEEE `float` (4 bytes), IEEE `double` (8 bytes) and “extended precision” (10 bytes; some systems only). The `float` type is heavily used in 3D applications (e.g., games), and the `double` type is *de rigueur* in scientific applications. Other domains vary (e.g., financial apps often use fixed point). – Donal Fellows Jan 05 '11 at 12:43
0

I don't think it's c# problem. c# is a general purpose language and gives you basic data types to play with. If you are not happy with them you are always free to create your own.

Moreover c# isn't the one who accept inaccuracy. Programmer does. For large set of problems inaccuracy is acceptable. Float shouldn't be used when exact result is expected but this is decision for programmer not for language designer.

Jakub Šturc
  • 35,201
  • 25
  • 90
  • 110
0

One reason is that numbers and number formats are unambiguous and universal. Yes, there are rounding errors, but they are constant and predictable. Trying to set up a general format for any algorithmic problem is not trivial.

Martin Hennings
  • 16,418
  • 9
  • 48
  • 68
0

There's a bit of an explanation here for mathematica

The short version is for regular day to day floating point math, the hardware can do it quickly with a known amount of inaccuracy. So if your calculation doesn't rely on being more precise, then do it the quick way.

If you do need the precision, then the programmer has to write the algorithm to the degree of precision required. Which will be slower.

Tom B
  • 2,160
  • 2
  • 13
  • 15