Binary floating point numbers vs. Scaled Decimals

So far I haven’t seen anyone answer this correctly.

In Javascript (or in C and Java, for that matter) 0.1+0.1 == 0.2 is true then what does 0.1+0.2 == 0.3 evaluate to? The answer surprises most people, because it’s false. Try it right now, go to your browser’s address bar and type in javascript:alert(0.1+0.2); and you’ll get 0.30000000000000004 and that’s not 0.3, is it?

This is because the fractions in Java, C or Javascript are binary floating point fractions. This means that when converting to decimal numbers (the numbers we type by hand) there’s a loss of precision. So 0.1+0.1 happens to be correct, but 0.1+0.2 happens to have a small error. Notice that using more precision wouldn’t help the problem, it doesn’t matter how many zeroes we get before we get the 4, the == operator will still say the two numbers are not equal.

The representation of 0.1 in binary is 0.000(1100) where parentheses mean repeating. This is because diving by 5 in binary numbers yields a repeating fraction, kind of like diving by 3 in the decimal world. So depending on how many bits we leave for the exponent vs. the significant it changes at which point we cut the repeating fraction off. As we saw, this leads to inaccurate representations of decimal numbers.

So why are binary floating point numbers used at all? The only reason is speed. Specialized computer hardware uses binary floating point fractions to make quick calculations. In languages like Java there’s a specialized BigDecimal class for decimal fractions

I would argue that decimal fractions and arbitrary-precision arithmetic should be the default for a general use programming language. Binary floating point numbers should be accessed in a more awkward way, not the other way around.

Consider the following Java snippet:

BigDecimal x = new BigDecimal(0.1);

Do you see the mistake? We passed a double into the BigDecimal’s constructor, so now the value of the BigDecimal is not 0.1 at all. Again, this is very counter-intuitive because you need to pass a string into its constructor like so:

BigDecimal x = new BigDecimal("0.1");

Just the fact that there is no way to write an accurate literal for 0.1 makes a strong case for scaled decimals to be the default representation. Remember, the decimal base is the default for integers because we write numbers in the decimal base. So why should that not be the case for fractions?

Advertisements

Messing around in the Newspeak workspace

I’m going to attempt to continue Exploring Newspeak Workspace by writing some more code.

Let’s try using x in the workspace:

x. (*Evalutes to MessageNotUnderstood*)

So let’s try fixing it:


| x |
x. (*Evaluates to nil*)

Here I used the syntax for a slot to “declare” x. Newspeak now understands this message since a getter was generated for it. So the message x is now understood and gets the contents of x, which is now null. Note that I put a dot at the end of every statement, even though some people use it as a separator and omit it at the last statement, so | x |x is just as valid.


| x |
x::5. (*Evaluates to 5*)

Not only did the getter get generated, but also the setter. See Setter Sends in the Newspeak Language for an in-depth explanation.


| x |
x::5 raisedTo: 5+3 negated. (*Evaluates to 25*)

This shows the precedence rules of Newspeak. This is equivalent to something like here.setX(5.raisedTo(5.+(3.negated()))) and returns the value set to x.

Now let’s move on to closures. The basic syntax for closures is [ :arg1 :arg2 ... :argN | statements] where the last statement is the value of the closure. You call closures by passing the message value: with the correct number of arguments.


[5. 6.] (*Evaluates to [closure]*)
[5. 6.] value (*Evaluates to 6*)
[:a | 5. 6.] value: 4. (*Evaluates to 6*)
[:a | 5. a.] value: 4. (*Evaluates to 4*)

Newspeak has reserved words for true and false which are unique instances of classes True and False. Those classes have the methods ifTrue: and ifFalse: and also ifTrue:ifFalse:. If we inspect those classes we can see that they take closures as parameters. true ifTrue: [a] ifFalse: [b] returns a value, false ifTrue: [a] ifFalse: [b] returns b value. Because of this, Newspeak doesn’t need control structures, they are defined in the language itself! The compiler should be smart enough to optimize these anyway.

So here’s an example using these message sends:

[:a :b | a > b ifTrue: [a] ifFalse: [b]] value: 3 value: 5. (*Evaluates to 5*)

This closure gives us the bigger of the two numbers. We can even assign it to a variable:

|max = [:a :b | a > b ifTrue: [a] ifFalse: [b]].|
max value: 3 value: 5. (*Evaluates to 5*)

In fact, we can even recurse inside the closure:

|fact = [:x | x < 1 ifTrue: [1] ifFalse: [x * (fact value: x - 1)]].|
fact value: 5. (*Evaluates to 120*)

Because that code is in a closure, we delay its evaluation. If we simply passed fact value: then it would infinitely recurse going into fact and never being able to resolve it. So to wrap this post up we’re going to print stuff to the Transcript which is in the Console window. Click the little cog at the top right of the window and select Show Console Window.


|fact = [:x | x < 1 ifTrue: [1] ifFalse: [x * (fact value: x - 1)]].|
platform Transcript cr; show: ((fact value: 5) printString). (*prints a carriage return and 120 in the Transcript*)

Because we don’t care about the return of the cr message (which just prints a carriage return to the Transcript) we just put a semicolon after platform Transcript cr so that we can send it another message to show some text. Note that the TranscriptStream’s show: method sends a message asString to its argument. The value we passed into the fact closure is 5 which is a SmallInteger which understands all the messages in the closure and our result is also 120, which is another SmallInteger. But SmallInteger doesn’t understand the message AsString, so we have to send the message printString which returns a string that does understand this message.


|fact = [:x | x < 1 ifTrue: [1] ifFalse: [x * (fact value: x - 1)]].|
fact value: 5.
1 to: 10 do: [:n | platform Transcript cr; show: (fact value: n); show: ' is the factorial of '; show: n]. (*prints the factorial from 1 to 10 in the transcript*)

The to:do: message executes the block passed to it with the do: keyword with the Number n and then sets n to n+1 while n is less than the stop value passed to it by the to: keyword. You can inspect this method yourself. As you inspect further, however, a lot of the methods actually get in-lined by the compiler for speed. Yet, you can appreciate how many features of the language are just message sends instead of special language constructs.

And this example is enough to show you how code in Newspeak looks like. While Newspeak is very minimalistic in its design, this doesn’t detract from its expressive power.