2017-02-10 9 views
5

Пока используется точка с плавающей запятой, 0,1 не может быть точно указана в памяти, поэтому мы знаем, что это значение обычно достигает 0,10000000000000004.Почему 0.1 + 0.2 получает 0.3 в Google Go?

Но при использовании следует добавить 0,1 и 0,2. Я получаю 0,3.

fmt.Println(0.1 + 0.2) 
// Output : 0.3 

Почему 0,3 выходит вместо 0,30000000000000004?

+0

Убедитесь, что Go не постоянна раз выражение, потому что Go использует дополнительную точность во время компиляции. – user2357112

+0

Благодаря новой вещи! – Integral

ответ

5

Это связано с тем, что при печати (например, с пакетом fmt) функция печати уже округляется до определенного количества цифр.

Смотрите этот пример:

const ca, cb = 0.1, 0.2 
fmt.Println(ca + cb) 
fmt.Printf("%.20f\n", ca+cb) 

var a, b float64 = 0.1, 0.2 
fmt.Println(a + b) 
fmt.Printf("%.20f\n", a+b) 

Output (попробовать его на Go Playground):

0.3 
0.29999999999999998890 
0.30000000000000004 
0.30000000000000004441 

Сначала мы использовали constants, потому что по-другому, чем при использовании (непостоянные) значения типа float64. Числовые константы представляют собой точные значения произвольной точности и не переполняются.

Но при печати результата ca+cb, постоянное значение должно быть преобразован в непостоянное, набранном значение, чтобы иметь возможность быть передано fmt.Println(). Это значение будет иметь тип float64, который не может точно представлять 0.3. Но fmt.Println() будет округлять его до 16 цифр, которые будут 0.3. Но когда мы явно заявляем, что хотим, чтобы он отображался с 20 цифрами, мы увидим, что это не точно. Обратите внимание, что только 0.3 будет преобразован в float64, поскольку постоянная арифметика 0.1+0.2 будет оцениваться компилятором (во время компиляции).

Далее мы начали с переменным типа float64, и не удивительно, выход был не 0.3 точно, но на этот раз даже по умолчанию округления мы получили результат, отличный от 0.3. Причина этого заключается в том, что в первом случае (константы) было преобразовано 0.3, но на этот раз оба 0.1 и 0.2 были преобразованы в float64, ни одна из которых не является точной, и добавление их привело к числу, имеющему большее расстояние от 0.3 , достаточно большой, чтобы сделать «визуальный внешний вид» с округлением по умолчанию пакета fmt.

ЗАКАНЧИВАТЬ аналогичные/актуальные вопросы + ответы, чтобы узнать больше об этой теме:

Why do these two float64s have different values?

How does Go perform arithmetic on constants?

Golang converting float64 to int error

Does go compiler's evaluation differ for constant expression and other expression

Why does adding 0.1 multiple times remain lossless?

Golang Round to Nearest 0.05

Go: Converting float64 to int with multiplier

+0

Спасибо! жаль, что я опаздываю. Это очень помогло! – Integral