It seems like go and C++ are doing something different regarding floating point arithmetic, but I cannot say one is better than the other. It is just the that C++ consistently overshoots (hence truncation work), and go consistently undershoots (this is why rounding is needed). For example, in C++:
F(59) = 956722026041.002 And in go, it is: F(59) = 956722026040.999878 And for example: On Monday, 30 April 2018 02:13:49 UTC+3, Michael Jones wrote: > > Not sure what you mean with "by design." The design here is the IEEE > Standard for Floating-Point Arithmetic (IEEE 754). It is authoritative for > Intel, AMD, IBM, Sun, etc. > > Typical (universal?) C and C++ implementations map 'float' to 32-bit IEEE > 754 binary floating point and 'double' to the related 64-bit version. Go > uses this same hardware in the same (universal?) way, through the types > "float32" and "float64." > > Truncation of floating point types to integer, or the floor() function, > discards any fractional part. Such that: > int(e) => 2 > int(pi) => 3 > > Rounding up to the nearest integer with int(v+0.5) and floor(v+0.5) is a > different operation: > round(e) => 3 > round(pi) => 3 > > Your C program truncates and your Go program rounds. They are not the same > program. They compute different things, which is why the results are > different. > > In a de Moivre coding of Fibonacci evaluation using rounding as above, > Knuth showed that the pow((1-sqrt(5))/2,n) term--the second summand--may be > dropped. > > For 64-bit floating point the F(75) value is the most that you can > generate this way. > > Using other methods you can (and more quickly) generate values up to > F(92), which is the greatest Fibonacci value (7540113804746346429) > representable as a 64-bit unsigned integer. > > For completeness, there is also the Ceiling function: > ceil(e) => 3 > ceil(pi) => 4 > > hope this helps. > > > On Sun, Apr 29, 2018 at 12:36 PM Yuval Lifshitz <yuv...@gmail.com > <javascript:>> wrote: > >> in C/C++ (at least on my system) "float" 4 has 4 bytes (32bits) and >> double has 8 bytes (64bits). according to this: >> https://golang.org/pkg/math/ its is the same thing with go. >> >> On Sunday, 29 April 2018 22:27:23 UTC+3, Louki Sumirniy wrote: >>> >>> I could be wrong but float64 is 'float' and 'double float' is float128. >>> I dunno, I have not tinkered with these imprecise math types. That's just, >>> essentially, what they were back in the olden days, like 20 years ago. 64 >>> bit was basic float, 128 was double. I have been out of the loop for way >>> too long on these things (and I am not a fan of floats anyway, give me some >>> fixed precision pls). >>> >>> On Sunday, 29 April 2018 10:08:15 UTC+3, Yuval Lifshitz wrote: >>>> >>>> (1) I understand the issue of limited precision, this is why I did not >>>> try anything above F(59) But my concern was not the difference between >>>> algebra and the go implementation it was the different results I got with >>>> the C/C++ implementation (gcc 7.3.1): >>>> >>>> #include <math.h> >>>> >>>> const double sqrt_5 = sqrt(5.0); >>>> const double phi = (1.0 + sqrt_5)/2.0; >>>> const double psi = -1.0/phi; >>>> >>>> // find the nth fibonacci number based on Binet's formula >>>> // see here: >>>> https://en.wikipedia.org/wiki/Fibonacci_number#Closed-form_expression >>>> unsigned long long fibonacci(unsigned n) >>>> { >>>> return (unsigned long long)((pow(phi, n) - pow(psi, n))/sqrt_5); >>>> } >>>> >>>> >>>> (2) Thanks for the fix, work well for the go implementation. However, >>>> if i try to apply it on the C++ one (where there is no rounding), it makes >>>> some of the tests fails. So, I guess that without rounding, the psi part >>>> is >>>> needed >>>> >>>> (3) Is there a way to print the map ordered (didn't see that in your >>>> snippet)? >>>> >>>> (4) Wanted to compare "double" in C++ to "float64" in go. As they >>>> should consume same amount of memory, have similar algorithms etc. but >>>> good >>>> to know about the "big" package in go >>>> >>>> (5) Thanks for the reference. interesting read >>>> >>>> On Saturday, 28 April 2018 00:57:42 UTC+3, Michael Jones wrote: >>>>> >>>>> Yuval, >>>>> >>>>> There are fundamental issues here. >>>>> >>>>> 1. That equation (de Moivre, Binet) is from the algebra of ideal >>>>> numbers. Numbers of infinite precision. Not the realm of computer >>>>> arithmetic. It works fine with double precision (go: float64, c/c++: >>>>> double) up to F(75) but must fail for F(76) due to the limited precision >>>>> of >>>>> 64-bit floating point and has nothing to do with language. >>>>> >>>>> F(76) = 3416454622906707 but the best we can do in 64 bits is >>>>> 3416454622906706 even with a Pow() function good to +/-1 least >>>>> significant >>>>> bit. >>>>> >>>>> 2. Another difference between algebra and computer arithmetic >>>>> (well...actually about the floor function) is that one of your two power >>>>> terms is not needed. Psi < 1 so Psi^N is pretty small, so small, that it >>>>> never changes the value of the rounded result. So you can just evaluate: >>>>> >>>>> return round(math.Pow(math.Phi, float_n) / sqrt_5) >>>>> >>>>> 3. Using a map in your test is not wrong, but it means that the tests >>>>> will be executed in a random order, which makes the printed errors a >>>>> little >>>>> less clear. >>>>> >>>>> celeste:fib mtj$ go test -v >>>>> === RUN Test_fibonacci >>>>> --- FAIL: Test_fibonacci (0.00s) >>>>> fib_test.go:104: 82 : Expected 61305790721611591 got 61305790721611584 >>>>> fib_test.go:104: 84 : Expected 160500643816367088 got >>>>> 160500643816367040 >>>>> fib_test.go:104: 81 : Expected 37889062373143906 got 37889062373143896 >>>>> fib_test.go:104: 87 : Expected 679891637638612258 got >>>>> 679891637638612096 >>>>> fib_test.go:104: 88 : Expected 1100087778366101931 got >>>>> 1100087778366101632 >>>>> fib_test.go:104: 83 : Expected 99194853094755497 got 99194853094755488 >>>>> fib_test.go:104: 77 : Expected 5527939700884757 got 5527939700884756 >>>>> fib_test.go:104: 86 : Expected 420196140727489673 got >>>>> 420196140727489600 >>>>> fib_test.go:104: 90 : Expected 2880067194370816120 got >>>>> 2880067194370815488 >>>>> fib_test.go:104: 91 : Expected 4660046610375530309 got >>>>> 4660046610375529472 >>>>> fib_test.go:104: 92 : Expected 7540113804746346429 got >>>>> 7540113804746344448 >>>>> fib_test.go:104: 76 : Expected 3416454622906707 got 3416454622906706 >>>>> fib_test.go:104: 85 : Expected 259695496911122585 got >>>>> 259695496911122528 >>>>> fib_test.go:104: 89 : Expected 1779979416004714189 got >>>>> 1779979416004713728 >>>>> fib_test.go:104: 79 : Expected 14472334024676221 got 14472334024676218 >>>>> fib_test.go:104: 80 : Expected 23416728348467685 got 23416728348467676 >>>>> FAIL >>>>> exit status 1 >>>>> FAIL fib 0.003s >>>>> >>>>> updated fib.go: https://play.golang.org/p/N-8lmjrMYAq >>>>> update fib_test.go: https://play.golang.org/p/FPuN58m1VVs >>>>> >>>>> 4. Plenty of ways to do this computation in Go using 64-bit integers, >>>>> or big floats, or big ints. >>>>> >>>>> 5. Plenty of algorithms, some quite fascinating! >>>>> https://ir.library.oregonstate.edu/downloads/t435gg51w >>>>> <https://www.google.com/url?q=https%3A%2F%2Fir.library.oregonstate.edu%2Fdownloads%2Ft435gg51w&sa=D&sntz=1&usg=AFQjCNFeFx9ebd-m_yzIjw4H29wdLpzmVw> >>>>> >>>>> >>>>> On Thu, Apr 26, 2018 at 10:22 AM, Ian Lance Taylor <ia...@golang.org> >>>>> wrote: >>>>> >>>>>> On Thu, Apr 26, 2018 at 1:17 AM, Yuval Lifshitz <yuv...@gmail.com> >>>>>> wrote: >>>>>> > >>>>>> > I ran into the following issue when started playing with go. Had the >>>>>> > following small program to calculate Fibonacci numbers using the >>>>>> closed >>>>>> > form: >>>>>> > >>>>>> > package "fib" >>>>>> > >>>>>> > import "math" >>>>>> > >>>>>> > var sqrt_5 = math.Sqrt(5.0) >>>>>> > var psi = -1.0/math.Phi >>>>>> > >>>>>> > // had to add this to solve accuracy issue >>>>>> > func round(x float64) uint64 { >>>>>> > return uint64(math.Floor(x + 0.5)) >>>>>> > } >>>>>> > >>>>>> > // find the nth fibonacci number based on Binet's formula >>>>>> > // see here: >>>>>> > >>>>>> https://en.wikipedia.org/wiki/Fibonacci_number#Closed-form_expression >>>>>> > func fibonacci(n uint) uint64 { >>>>>> > float_n := float64(n) >>>>>> > return round((math.Pow(math.Phi, float_n) - math.Pow(psi, >>>>>> > float_n))/sqrt_5) >>>>>> > } >>>>>> > >>>>>> > >>>>>> > When I first tried without doing the "rounding" I did not get whole >>>>>> numbers >>>>>> > as the output (similar program in C++ gave whole numbers without >>>>>> rounding). >>>>>> > Following test is failing without the call to "round()": >>>>>> > >>>>>> > package "fib" >>>>>> > >>>>>> > import "testing" >>>>>> > >>>>>> > var results = map[uint]uint64 { >>>>>> > 0: 0, >>>>>> > 2: 1, >>>>>> > 10: 55, >>>>>> > 14: 377, >>>>>> > 20: 6765, >>>>>> > 29: 514229, >>>>>> > 33: 3524578, >>>>>> > 59: 956722026041, >>>>>> > } >>>>>> > >>>>>> > func Test_fibonacci(t *testing.T) { >>>>>> > for arg, expected := range results { >>>>>> > actual := fibonacci(arg) >>>>>> > if actual != expected { >>>>>> > t.Error("Expected", expected, "got", actual) >>>>>> > } >>>>>> > } >>>>>> > } >>>>>> > >>>>>> > >>>>>> > >>>>>> > Are there known accuracy issues with floating points in go? >>>>>> >>>>>> No. >>>>>> >>>>>> I suggest that you show us your C code. Thanks. >>>>>> >>>>>> Ian >>>>>> >>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "golang-nuts" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to golang-nuts...@googlegroups.com. >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> Michael T. Jones >>>>> michae...@gmail.com >>>>> >>>> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > > > -- > Michael T. Jones > michae...@gmail.com <javascript:> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.