New to GO- how it handles float precision 0.4 + 0.2 is 0.6

New to GO- how it handles float precision 0.4 + 0.2 = 0.6

I am new to chat and learning as value fact that Go is compiled, no classes, goto (exist).

I am still learning some old school BASIC and QBASIC (as good foundation books on programming) and Python and comparing differences with GO.

1990 QBASIC was dealing with single precision by default unless DIM AS DOUBLE:

print 0.2 + 0.4 gave correct 0.6

Python print(0.2 + 0 .4) gives float with 1 at end not 0.6, neither 0.2 + 0.4 == 0.6 (False)

I am positively surprised that there is good touch with GO on basic libraries gives 0.6

But it is still float64.

Can you let me know please how the library is not triggering floating point error, is there logic build not to show decimal places, if number does not have much decimal.
I am surprised many other languages fail as it was is manageable over 30 years ago. I like fact you can assign precision to var in front so small numbers don’t need to be run with high precision.

package main

import "fmt"

func main() {

fmt.Println(0.2 + 0.4)

fmt.Printf("%T\n", 0.2 + 0.4)

}

On other ascpects
I am comparing the input:

BASIC had numeric variable as default,
Python has string,
GO has scanln() as string

Division /

BASIC 5/2 will give 2.5 as \ was for integer division- most elegant solution

Python 2, 5/2 gives 2 as in GO 2 as integer division
Python 3 5/2 gives correct 2.5 as integer div is now //

I don’t like that GO has / as integer as that is rarely used, the should use \ for integer and / to float but if var is assigned as float in front then is ok and that what matters.

Can you let me know please some other obvious difference compared to Python.
I will buy book for sure, In easy steps as series was good Python and VB.

I will see GO getting adoption and will climb as basic libraries are done by professionals not by amateurs like elsewhere. Fact it can compile and fmt has lot of functions is good. Python you have to import everything, even to deal with time or math.

Thank you

Go’s float32 and float64 types follow IEEE 754, just like many other languages. This means that it will be subject to the same limitations.

package main

import "fmt"

func main() {
	fmt.Printf("%T %T\n", 0.2, 0.2+0.4) // float64 float64

	fmt.Println(0.2 + 0.4)                   // 0.6
	fmt.Println(float32(0.2) + float32(0.4)) // 0.6
	fmt.Println(float64(0.2) + float64(0.4)) // 0.6000000000000001
}

playground

Regarding fmt.Println(0.2 + 0.4), the expression contains only literal constants and as such will be evaluated at compile time rather than runtime.

2 Likes

Thank you for explanation. What I liked about QBASIC that still runs on DosBox on modern Windows, although I have also PC286 (12.5 MHz) and PC386 (40 MHz), it used single by default.
It is computational wasteful for most simply arithmetic’s to run float64 and causes error in Python IDLE shell even if typed without print just 0.2 + 0.4

I am surprise default is float64. I can get that float error still on my PC386 if I declare DIM n AS DOUBLE, but not with default single.
I very much like all the precision choices GO gives, different floats or integer signed and unsigned- toolbox is big, and one can use what it needs.

I understand that the language must comply to that IEEE 754 (I was aware of it), but it is like using 5 kg hammer for nail with double precision (they may call it nowadays bit different to past).
That is for user to learn and hope books explain it well what to use to make code faster.

To summarise fmt.Println(0.2 + 0.4) I understand now this is taken as value not as float
literal constants (google it)

This will create float error if assigned like that with := as runs float64 by default.
If it sees numbers small decimal spaces, cannot logic be made at compiler to treat as float32 at compiler as it cannot mathematically give that long decimal spaces in first time.
Fix that way with float32

package main

import "fmt"

func main() {
	a := 0.2
	b := 0.4
	fmt.Println(a + b) // 0.6000000000000001
}

I read some articles, blogs and nothing has changed:
• No float is good for any decimal analysis even float32 will cause errors.
• The Cobol had fixed point arithmetic’s at base 10- that works and good precision.
• Most in finance use integers
• Python out of box decimal module works as long as a = Decimal(‘0.1’) as string and comes with easy syntax. Some book teach a = Decimal(0.1) but that will cause problems, library allows to type as no string.
• GO does not have out of box decimal module , lots of proposals were put and there are third party libraries, but some are not good.

That does not help as no single standard as multiple choices and confusion, some standard would help to bring programs run with Cobol to GO.

At least for me, this isn’t a problem. If you want standards, you should go for proposals. But for a simple design, this just feels tedious to me.
If you want complete precision, don’t use float. This is basic development common sense. If you are worried that int64 cannot meet your value range, you can use big.Int.

I watched original release video from over 14 years ago.

The point was to declutter, time moved on. If generics are missing there is opposite effect if there are multiple libraries doing same things. None of decimal implementations including in Python are good to me, as gets ugly very quickly with visual noise. There are proposals but all would end up like Python, who wants to type Decimal(“0.2”) should be 0.2 only.

If to implement core to be treated as fixed point arithmetic’s with decent precision up to 9 to cover crypto and no added syntax. People could do their esotherics with float32 or 64 as variables anyway.

Of course they made originally GO for Google only.

Many generics are missing: like simply Tkinter equivalent GUI, what 1990 QBASIC had INKEY$ (to read input key), time, power, random was all out of box- single standard.

In Python multiple time function exist too. I still use QBASIC to prototype, VGA standard each color as integer, can draw on screen and use keys if needed and have plenty precision and instantly .exe too. QBASIC was compiling with two math options.

Out of box base 10, with 9 decimal spaces would be enough for generic use.

Thank you for replies – as I am learning more languages, guess discrepancies are started to be noticed on many things including mentioned / integer division in GO while BASIC it was / for float and as in Python 3 (Python 2 was / integer).

I would assume sticking to some single standard would help in industry.
GO still looks promising to me as compiled and although is complex not that as other languages – the new features I need to catch up that I am not familiar with and maybe good for new things to me I don’t have any comparator.

This recent article has a clear explanation.

Have you looked at: big package - math/big - Go Packages ?

The math/big package is included in the standard library, no third party, no imports needed. You have arbitrary precision for Integers or rational numbers or floating point arithmetic. This explicit choice will make you careful consider your use case and the best representation.

For example: If you are calculating irrational numbers you could never “complete” your calculation if you want to represent all the digits (since irrational numbers like sqrt(2) have an infinite amount of digits)

So depending on your use case the right implementation might be big.Float, big.Rat or big.Int or just the plain old Int or Float32/64 (e.g. when your values are serialized to other Services, which expect a float32)

1 Like

Thank you – it points on that constant, but is not that well explained.

Better to declare variable as const and both as default float64 or float32 works. As you mentioned it also treats n := 0.1 + 0.2 as constant, but not if each is declared separately.

I would not use any big math for simply arithmetic’s that is illogical to me.
Fixed point 8 decimal precision would be best but using constant trick works for simply math but difficult to use such.

package main

import "fmt"

func main() {
	const a, b = 0.1, 0.2
	fmt.Println("sum a(0.1) + b(0.2) = ", a+b) // Correct 0.3
	fmt.Printf(" a is %T\n b is %T\n", a, b)

	n := 0.1 + 0.2
	fmt.Println("sum n(0.1 + 0.2) = ", n) // Correct 0.3
	fmt.Printf(" n is %T\n", n)

	c := 0.1
	d := 0.2
	fmt.Println("sum c(0.1)+ d(0.2) = ", c+d) //  !!! InCorrect 0.30000000000000004
	fmt.Printf(" c is %T\n d is %T\n", c, d)

Also for loop figured out will work if declared as constant it will not overflow

I just changed c and d as a and b ang got the same result. Say
c, d := 0.1, 0.2…

I am learning and have not installed yet GO to compile to see what difference it makes.
I seems to work only well predictable if variable are set with const or if addition
n := 0.1 + 0.2

c, d := 0.1, 0.2 gives also incorrect 0.30000…4that is the point.

The link above explained how Go treats literals differently from variables. The link below explains why you do not get 0.3 when adding the values stored in variables. In fact, that is exactly the first thing mentioned there. Maybe you are just a troll bot.

I am familiar with that article and understand float precision hence titled question
how it handles float precision 0.4 + 0.2 = 0.6 and received answer for that- thank you.

I am not familiar with concept of Constant as neither BASIC or Python has it and latter gives different result 0.1 + 0.2 or 0.2+ 0.4, than GO hence my original question.
Excel deals with it as rounding and still float and that is hiding problem.

The very good summary text from previous article:

“x := 0.1 + 0.2 is precisely 0.3 because 0.1 and 0.2 are numeric constants”

Could be put there with some my above example to expand that tour segment and flag as warning how float32 or float64 behaves at base 2.
https://go.dev/tour/basics/15

Things may be obvious, but they aren’t and errors are even in books.
I learn Python and GO also from green book series in easy steps.

The Python decimal module on p 89 does not have information to put numbers as strings Decimal(‘ ’) I notified publisher and also regarding GO to expand on floating point, while old BASIC books and manuals had it (read ~5000 pages of old manuals and ~1000 p from old book since last year incl original 1964 release and code on old hardware 1986-93).

Decimal(0.1) + Decimal(0.2) will give error unless put as string Decimal(‘0.1’) + Decimal(‘0.2’), but allows to add one as string and one as not and easy to make such error.

GO has stable syntax hence it is very good language and I value simplicity.
Cobol deals best decimal as integers- elegant solution and most safe than converting to strings like many modules do.

With GO I also go to beginning too – hence watched mentioned launch video. Interesting is why they have not put originally simple Cobol solution for decimal out of box to avoid all the third party decimal modules and added syntax.
.

Your question is like asking why people still use float. This doesn’t make sense, because you’ll have to adjust which data structures you use for your own needs. I don’t care how elegant you say Cobol is, but in practice, most people can develop just fine without Cobol. This is not why you recommend using so-called Cobol over float.

Floats should not be used for any decimal calculations and are useful for other things the same like signed or unsigned integers or constants. What I meant to say there should be all sort of tools in tool box for different work including fixed point base 10 arithmetic’s.
I do not negate floats per say and use them too.

Finance including crypto mainly use integers for math and could be made easier with out of box simply library. Cobol is only one I seen with out of box solution.

I will play with MS-DOS Cobol 5.0 on PC 386 (40 MHz) to understand more fixed point arithmetics with integers based on proper old school standard.
Cobol, Fortran, Assembly and BASIC are at the end foundation of programming.

GO still has good options for integers and float by default and they must had reason not to add any simply fixed point arithmetics module based on integers.

Unless you use library Python does not allow you to use float32 out of box.

Here is Cobol

IDENTIFICATION DIVISION.
      
PROGRAM-ID. AddNumbers.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 NUM1 PIC 9V9 VALUE 0.1.
       01 NUM2 PIC 9V9 VALUE 0.2.
       01 RESULT  PIC 9V9.

       PROCEDURE DIVISION.
       BEGIN.
           COMPUTE RESULT = NUM1 + NUM2
           DISPLAY 'The sum of 0.1 and 0.2 is ' RESULT
           STOP RUN.

I don’t care what you do in python, if you know data structures you should know what data structures you should use to do your business. I can expect, the fixed-point arithmetic you’re talking about isn’t as efficient or intuitive as the integer representation.
At this point, I will not say anything, because no amount of my words can change your opinion.

I am exploring what programs have and what differences are. I know what I need for my end especially when all programs use floats. I just pointed out on few known facts and checking what modules are and how they are used.

I will use what is out of box in GO and ok with that, since others are on the same page.