7
$\begingroup$

I keep seeing students use float in lab lessons:

For example, a simple physics calculation of kinematics. Many, many students use float to hold the variables:

float y,g,t,v

etc.

In this specific lab, they idea is for them to see:

$$y(t_{n+1})=y(t_n)+\frac{\Delta y}{\Delta t}\Delta t\approx y(t_n)+v(t_n)\,(t_{n+1}-t_n)$$ with $$v(t_{n+1})\approx v(t_n)+g*(t_{n+1}-t_n)$$

and then run over times $\{t_i\}_{i=1}^n$ and see that the $y$ values they get are the same as:

$$y(t_n)\approx y(t_1)+v(t_1)\,t_n+\frac{1}{2}g\,t_n^2$$

However, because they use float, they get rounding errors when dealing with small time differences ($\Delta t$). I don't want to get into the whole floating point arithmetics field, because they won't understand that (the word "exponent" would frighten them, to say the least).

On the other hand, if they use double, then the rounding errors wouldn't be significant (because they aren't dealing with $\Delta t \le 10^{-5}$ of a second). So I try to explain that they should use double, but just stating it as a "rule of thumb" isn't a good idea (because there are cases where one would prefer float)

So, what explanation, as to why they should use double for these things, would be compelling?

Better yet, is there any way I can show the students such an explanation? (Perhaps an online, interactive demonstration of floating point precision etc. - I couldn't find one)

$\endgroup$
  • 1
    $\begingroup$ They should have done significant digits in maths class. e.g. “Write your answer to 3 significant digits” They spend a significant time on this. $\endgroup$ – ctrl-alt-delor Feb 13 '18 at 17:23
  • $\begingroup$ If they're doing this level of math, a little exponentiation won't hurt them. If memory serves correctly, this is 10th grade physics. Exponents are introduced in 5th to 6th grade, and polynomial functions occupy most of 7th through 9th grades. $\endgroup$ – pojo-guy Feb 13 '18 at 18:29
6
$\begingroup$

Better yet, is there any way I can show the students such an explanation? (Perhaps an online, interactive demonstration of floating point precision etc. - I couldn't find one)

Show them these bits of code:

float one = 16777291;
float two = one + 1;
System.out.println(one == two);

float one = 1.00000001f;
float two = one + .00000001f;
System.out.println(one == two);

Ask them what they expect these to print. They should print false, right? But when you run them, they print true!

Then explain that this is because float values can only hold a relatively small number of significant digits. Change the float values to be double values and run the code again, and you'll see that false is printed like we'd expect.

Explain that for many purposes float is enough precision, but not for this class. Explain that double has the same problem, but with much more precision. Explain that double precision is enough for this class, but if they need more precision in the future to use BigDecimal or something.

$\endgroup$
8
$\begingroup$

Luckily this is quite simple to make clear, even if you are steering clear of the IEEE standard. Honestly, even binary is not needed here.

I would start by borrowing a page from Scheme, and say that we can't make blanket guarantees about the exactness of decimal numbers. For instance, when we try to express $2/3$ in decimal, and it doesn't work!

All the more so when we are restricted to 10 digits. We write $0.666666667$. Why? It's not that 2/3 is $0.66666667$, it's just that we can't precisely represent $2/3$ in decimal, and at the 10th digit, we just round to get as close as we can.

This is really a problem with any number that has a decimal place. There are infinite numbers that we can't represent!

The computer has the same problem with decimal numbers as we do. This isn't a fault of the computer, it's just a feature of floating point numbers, and the computer has to work around it, just like we do.

Now, we do have a way of increasing that precision: we can increase the number of digits allowed. It doesn't solve the problem, exactly, but it does get us closer to the true numbers.

That's the difference between a float and a double. A double allows more digits. And that's why it's usually a better idea to use a double.

$\endgroup$
  • $\begingroup$ Add to this, floating point processors since at least the '90s have always converted float to double, easily costing any efficiency they may think to have gained by using the smaller float. $\endgroup$ – pojo-guy Feb 13 '18 at 17:57
  • 2
    $\begingroup$ @pojo-guy, Can you provide a reference for that (floating point processors since at least the '90s have always converted float to double). Or, do you just mean up-conversion in mixed-type operations? aFloat + aDouble, for example. $\endgroup$ – Buffy Feb 15 '18 at 14:03
  • $\begingroup$ I'll have to dig up the specs on the 80387 and 68881 math co-processors. It's been a few decades. $\endgroup$ – pojo-guy Feb 15 '18 at 15:31
  • $\begingroup$ Chapter 2.1 of the 80387 programmers manual - "Eight individually-addressable 80-bit numeric registers, organized as a register stack", and MC68881 reference manual "8 general purpose floating point registers, each supporting a full 80 bit extended precision real data format" . The processors had no facilities for handling "float", apart from converting to and from extended precision. $\endgroup$ – pojo-guy Feb 15 '18 at 16:38
  • 1
    $\begingroup$ Modern processor architectures usually have dedicated facilities for single-precision and double-precision computation (x86: see multiple variants of SSE and AVX). Single-precision computation typically provides significant performance advantages (in particular on GPUs) via higher throughput of functional units, lowered bandwidth requirements, and also provides energy savings. Now: Significant research into computing with mixed precision, where most computation is done in single precision and only final refinements in double precision, e.g. work by Stan Tomov and Jack Dongarra. $\endgroup$ – njuffa Feb 21 '18 at 17:46
5
$\begingroup$

Tell the students they have seven decimal digits of precision in a float, and that the decimal point is placed "somewhere" within those seven digits, depending on the magnitude of the number.

Ask them to add 0.01 to 9,999,999 and express the result to seven digits. Ask what the answer would be if they performed the addition a thousand times.

Now ask them to do the same calculation using 15 digits of precision.

$\endgroup$
  • $\begingroup$ As ctrl-alt-delor commented much earlier, the key to understanding float vs. double is the number of significant digits. More specifically, students should learn that computer arithmetic is finite-precision arithmetic. $\endgroup$ – Bob Brown Feb 23 '18 at 12:42
2
$\begingroup$

Actually, it isn't quite so clear. If I run this in Java:

// Simple computation with float and double
// Increment by a third three times is not the same as incrementing by one
// Float can actually be more accurate than Double in limited cases
public static void main(String[] args) {
    float oneThirdF = 1.0f/3.0f;
    float wholeF = 0.0f;
    float countF = wholeF; //initially equal
    while(countF == wholeF){
        wholeF = wholeF + oneThirdF + oneThirdF + oneThirdF;
        countF = countF + 1.0f;
    }
    System.out.println("Float: " + countF + " != " + wholeF);

    double oneThirdD = 1.0d/3.0d;
    double wholeD = 0.0d;
    double countD = wholeD; //initially equal
    while(countD == wholeD){
        wholeD = wholeD + oneThirdD + oneThirdD + oneThirdD;
        countD = countD + 1.0d;
    }
    System.out.println("Double: " + countD + " != " + wholeD);

}

I get:

Float: 3.0 != 2.9999998
Double: 2.0 != 1.9999999999999998

So, while doubles are certainly more precise than floats, the place in a "floating point" computation at which things go wrong depends on a lot more than which form you use. Here Float was a bit more "accurate" initially, since Double failed earlier.

Lessons: Don't use such things for counting. If you need to do computation use the form with more precision. Beware of the results. And testing for equality is pointless (it's why Zeus created Epsilon).

Finally, though this code doesn't illustrate it, there are situations in which the errors are larger than the answers, so saying x ± ε might be entirely meaningless if x is small and ε is large.

However, if your use is to take a physical reading from some sort of equipment (say temperature) and report it, with little computation, the shorter (float) type is almost certainly sufficient and likely has more precision than necessary. When there is a lot of computation, use double along with sophisticated error control techniques.


For a (long) explanation of floating point errors see: https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html. This is valid for any language using the IEEE 754 standard (most modern languages and processors).

$\endgroup$
  • $\begingroup$ ... and never use floating point to represent money. At 11 million dollars plus or minus you start losing the pennies, and your company's accountant will feed you to the alligators slowly. $\endgroup$ – pojo-guy Feb 15 '18 at 15:38
  • 1
    $\begingroup$ @pojo-guy Actually money is one of the most complex data types. It has both place and time dimensions. It means something different today than in 6 months and it means something different in the US and the EU. An early chapter in martinfowler.com/books/ap.html explains the complexity. $\endgroup$ – Buffy Feb 15 '18 at 15:45
1
$\begingroup$

Many compilers will promote floats to doubles, do the calculation, and cast back. I see little or no reason to use floats unless one is dealing with huge matrices of floating-point numbers. I encourage my students to use doubles for most purposes.

$\endgroup$
  • $\begingroup$ In many resource-constrained settings, like GPGPU work (or just GPU work in general), using floats is necessary. We're using 16-bit floats and 16-bit ints in a lot of circumstances to reduce memory pressure and increase execution speed. If you're writing a website, go ahead and use doubles. If you're writing a game, simulator / numerical modeling, etc., or anything heavy on GPU usage, use the smallest data type that meets the needs of the application. $\endgroup$ – 3Dave Sep 13 '18 at 15:35
1
$\begingroup$

Simple demonstration of "precision" using handheld calculators.

Get a pair of calculators. One cheap model that has a limited number of digits in its display. Models can be found built in to clipboards and other "office" things. One decent model, not necessarily a good model, that has double the digits of the other calculator. If it has exactly double the display size of the first, so much the better.

One point to be aware of is that many calculators, even the cheap disposable ones, will have at least one significant digit beyond the display to help hide/correct rounding errors. The demonstration will have to be tested on the specific models you use before class.

Develop some short, and simple, formulas that will develop rounding errors quickly. Thirds, and harmonics thereof, usually are corrected by the hidden digit(s), but higher factors tend to do better. It can be helpful to also avoid returns that go into scientific notation value range - six or seven digits left or right of the decimal place is probably the best range to stick with. Something involving 3 or 4 digit primes as numerators and denominators should do the trick.

Having the two calculators in hand, and your pre-tested formulas, have the students work out by hand, or follow you as you do, the formulas, so that they will know what the real answers are. Run the same formulas on the cheap calculator, showing where it starts to go wrong, and how fast it gets worse. Run the same formulas on the better calculator, showing how much farther into the formulas it gets before it starts to drift, and how much, less, it gets it wrong. If the demonstration has one formula that actually finishes correctly on the better calculator, but not the cheap one, so much the better.

Having the other formulas not come out completely correct, even on the better calculator, leaves room for you to explain why/how rounding errors in float/double can affect programs. Adding in a formula or two that can then be run on the computer (language of choice) that shows the error delta can help drive the point home. If it's also one where they might be tempted to opt for float that is even better.

$\endgroup$
0
$\begingroup$

I would highly recommend this Answer to question what the "Difference between float and double" is.

If not already done in introduction, i would show the math behind floating point representation on a computer (exponent, mantissa, ...). That shall clearly state the difference between those data types and explain why in physics it is not a good idea to CUT precision. If necessary and for fun reason use 64bit datatypes and calculation.

There is one thing where I have trouble with some answers. For good reason never ever teach the comparison of two floating point numbers or in loop counts, etc. The Reason for that can be found in the CERT C Guides Link!

$\endgroup$
  • $\begingroup$ My question is specifically about avoiding showing the mantissa. They wouldn't understand that. $\endgroup$ – ItamarG3 Feb 14 '18 at 7:50
  • 2
    $\begingroup$ @ItamarG3, If your students really are incapable of understanding what floating point numbers are, then IMO you might as well just say, "Because I told you to," and leave it at that. $\endgroup$ – Solomon Slow Feb 14 '18 at 17:50
  • 2
    $\begingroup$ P.S., as other answers have pointed out, you don't have to explain binary floating point. Decimal is easier to understand, and if you talk about decimal, then "exponent" just means, "move the decimal point this many places to the right or left." $\endgroup$ – Solomon Slow Feb 14 '18 at 17:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.