Точность выпуска Голанга большая - PullRequest
0 голосов
/ 14 мая 2019

Я столкнулся с интересной проблемой вычисления Голанга. Поплавок.

Проблема

10001000100010001000100010001000100010001000100015.5533 / 1000000000000000000

= 10001000100010001000100010001000.1000100010001000155533

Тем не менее, big.Float дал "10001000100010001000100010001000,10001000100010001555329999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999997"

код:

var prec uint = 1024 // 512
dec, _ := new(big.Float).SetPrec(prec).SetString("1000000000000000000")
f, _ := new(big.Float).SetPrec(prec).SetString("10001000100010001000100010001000100010001000100015.5533")
q := f.Quo(f, dec)

fmt.Printf("Percision: %d\n", prec)
fmt.Printf("Quotient: %s\n", q.Text('f', -1))

Результат:

Percision: 1024
Quotient: 10001000100010001000100010001000.10001000100010001555329999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999997

И более запутанная часть, если я устанавливаю prec = 512, меньшую точность, она дает правильный результат.

Percision: 512
Quotient: 10001000100010001000100010001000.1000100010001000155533

Кто-нибудь знает, что не так с моим кодом или как настроить big.Float для получения ожидаемого результата?

Спасибо всем!

1 Ответ

4 голосов
/ 14 мая 2019

С go doc math/big.Float:

Конечное число, отличное от нуля, представляет число с плавающей запятой с высокой точностью

знак × мантисса × 2 ** экспонента

с0,5 <= мантисса <1,0, и MinExp <= экспонента <= MaxExp. </p>

И SetPrec устанавливает битовую ширину мантиссы, а не некоторую десятичную точность.

Как и в случае с float64s, а не с каждой десятичной дробьючисло может быть представлено точно в большом. Float, и ваш код показывает это.Тот факт, что вы видите то, что вы ожидаете увидеть с prec = 512, связан с различным округлением и печатью.

Правило большого пальца: большие. Плавания ведут себя как «обычные» поплавки со всеми их недостатками (здесь не каждый десятичный знакдробь может быть представлена), но может показывать меньше ошибок округления.

...