B+.. More math trouble (decimal related)..

Blitz3D Forums/Blitz3D Beginners Area/B+.. More math trouble (decimal related)..

BachFire(Posted 2003) [#1]
Hey,

First, some code:

Graphics 640,480
SetBuffer BackBuffer()

b=20

Text 20,b,"Should be 53.36: "+Float(5.8)*9.2
b=b+15:Text 20,b,"Should be 31738.47: "+Float(1661.7)*19.1
b=b+15:Text 20,b,"Should be 32767.1226: "+Float(385.49556)*85

b=b+30:Text 20,b,"Hit ESC to quit.."

Flip

While Not KeyHit(1)
Wend


Why are all the decimals present in the first one, but not in the rest? In the last two, it's truncated to only 1 decimal. Is there some way, to force any number of decimals, or something? Or what's wrong here..

Thanks for the help. ;)


Myke-P(Posted 2003) [#2]
I remember it's *something* to do with the "Single Precision" float type used by Blitz? Either way it looks like you get a maximum of 6 acurate figures followed by 0s (zeros).

b=b+15:Text 20,b,"Should be 3276712.26: "+Float(385.49556)*8500 ;Actual result = 3276710.0


Someone else may well be able to elaborate further, but whatever the reason, it's nothing you're doing wrong (or can do anything about.)


Floyd(Posted 2003) [#3]
Floating point numbers are single precision and are displayed with six digit accuracy.
Graphics 500, 400, 0, 2

x# = 2.0
y# = 2.0000002
z# = 2.0000001

Text 50, 10, "x = " + x
Text 50, 30, "y = " + y
Text 50, 50, "z = " + z

If x <> y Then Text 50, 70, "x and y are different"

If x = z  Then Text 50, 90, "x and z are equal"

WaitKey



BachFire(Posted 2003) [#4]
Thanks a lot you guys, but I still don't understand..

When I try Floyd's code bit, it displays that x, y and z are all '2.0', and x and y are different, and x and z are equal. Is that what's supposed to happen? If so, I don't see the logic, I'm sorry..

How can I get more than one decimal, and why was the first one in my code (top of thread) NOT 1 decimal, but 2..?


Anthony Flack(Posted 2003) [#5]
Okay... first up, you don't need those float() commands in your code.

As to your confusion, floating point variables have 6 digits of precision. Therefore you can have 1.37484 (6 digits) or 57391.6 (6 digits) or 749.547 (6 digits)... but no more. Hence floyd's example:

x=2.0
y=2.0000002 - which, when reduced to 6 digits, comes out as
y=2.00000

therefore x and y are equal.

One other thing - you can also store values like 468234000.0, which looks like more than 6 digits, but it's actually just 6 with the decimal point moved way back...

Perhaps one day, we will get double precision floats...


BachFire(Posted 2003) [#6]
Hey Anthony,

Thanks for clearing that up for me. I now understand what the 6 digits precision means. And my code makes sense to me now. I love it, when I understand something.. Thanks a lot. ;)

However, I can only partially see the logic of Floyd's code.. Because of the 6 digits precision, all of them (x, y and z) have the value 2.0 - right?? I therefore fully understand the last statement "x and z are equal", because they're both 2.0.. But I DON'T understand the FIRST statement "x and y are different", because they're NOT different - they're both 2.0.. They're all 2.0..

This does not make sense to me.. Sorry, if I'm slow.. I SO wanna understand this.. :-(


Floyd(Posted 2003) [#7]
This is hard to explain without going into a horrible amount of detail.
But here is my attempt.
======================================================

Imagine floats are base ten numbers, exactly 4-digit precision.

In this system the next number after 1.0 would be 1.001 = 1 + 1/(10^3).
There are no numbers in between.

Because of rounding, the assignment x=1.0007 actually sets x to 1.001.
Similarly x=1.0004 sets x to 1.000.

Now on to the way it really works...

Floats are actually base two, 24-bit precision. This means the next number
after 1 is 1 + 1/(2^23) = 1 + 1/8388608.

The example code shows x=y but x<>z despite that fact they are all displayed the same way.

z would be larger than x by one part in twenty million, if this were possible.
As the example shows, it is not.

The result is that x and z, as floats, are identical.

y is enough larger than x to be a different single precision number.

The code attempts to make y larger than x by one part in ten million.
This exact value is not possible. In fact, y is set to the next single precision
value after x, namely 2 + 2/(2^23). This is the *exact* value of y.

As to the six digit display, well that's just a compromise.
Unfortunately, Blitz doesn't let you format the displayed values.
If you could display more digits you would see x=z and x<y.

For example, with a 9-digit display y would appear as
2.00000024, which is the closest 9-digit number to 2 + 2/8388608.

With even more digits, y would display as 2.0000002384185791016.


Oldefoxx(Posted 2003) [#8]
Le me add a comment here or two:

Fractions are presented in the form 1234/5678, which is an incomplete division form. If the division is performed, the value may appear to be 0.2173300458, if your calculator can display that many places. A calculator with only an 8-digit display will only show 0.2173300. Which of these is the correct answer? How about 1/3, which is shown as 0.3333333333 on my calculator, buy may only show as 0.3333333 on yours. Do they agree? Are they the same? Are they truely accurate?

We have three considerations: Precision, accuracy, and range. How precisely a value can be represented, how accurate a value can be represented, and the range over which values can be represented.

As you probably learned in school, positive numbers can go towards infinity, negative numbers can go towards infinity, and fractions can go towards infinity, either getting bigger, or ever smaller as they approach zero. But infinity is not a place you can ever get to, it is a concept of there always being something more, something still reachable, without end.

So we cannot represent infinity when we build machines, because they are finite (have limits) by nature. The is always going to be a maximum large number or maximum small number involved, so while we can easily represent zero, there is no infinity, large or small, that we can represent or obtain using a machine.

In fact, we have no way at all of representing the concept of infinity in and of itself, within a computer. There is no "without end", unless you consider the infinite loop, which is a ceaseless process (but we can always stop it).

So we cannot have infinite precision, nor infinite accuracy, nor infinite range, when dealing with numbers, expressions, or results. We can only go so far. And because of this, we round off values. Either we do it, or the machine does it for us. And when we carry on computations involving rounded-off values, we get round-off errors. And the more complex the computations, the more likely that the round-off errors will grow in size and distort our results. The computer, in comparing two values, is looking for an exact match to the limits of its ability to accurately represent both values, or determine that one value is larger than the other. Because of round-off errors, the values represented may be such that the wrong value may appear to be larger, or they may appear to be equal when they truely are not, or they may appear to be slightly different when they should be exactly the same.

So, in general, you are not concerned with accuracy and round-off errors until you ask the computer to compare values for you, and then you run into the problem of round-off errors causing you grief. Well, the fact is, round-off errors give you an added half-bit of accuracy, where truncated values lack that feature. But truncated values also lead to truncation errors, which are at least as bad as round-off errors, and often worse.

So what is the answer? Round-off errors most commonly occur when you divide, so do all your multiplies first if you can. Instead of testing for exact matches, you may have to use the >= and <= test to see if a value is within an acceptable range. such as:

    If a#>=1.333 And a#<=1.334 Then

Or you could try...

    IF a#=Float(1/3) Then

Some programmers do not like that second form, because it means an extra divide step each time it is executed. But it means you are checking a# to the limits of the accuracy of the representation possible, and besides, a smart compiler could recognize the use of constants and here and store the results of 1/333 as an internal representation of 0.333333333333... to as many places as it can.

Still, round-off and truncation errors can haunt you, so just keep it in mind that you may have to try a variety of methods to narrow the error down to something you can live with.