Невозможно использовать указанные значения c float32 в качестве ключа карты - PullRequest
0 голосов
/ 07 апреля 2020

Использование float32 в качестве ключа карты возвращает неожиданный результат

package main

import "fmt"

func main() {
    result := make(map[float32]map[float32]float32)

    var t1 float32 = 1586238540
    var t2 float32 = 1586238600

    result[t1] = map[float32]float32{1:1,2:2}
    result[t2] = map[float32]float32{3:3,4:4}

    fmt.Println(result[t1])
    fmt.Println(result[t2])
}
map[3:3 4:4]
map[3:3 4:4]

Go версия: go version go1.14 linux/amd64

Изменение result на map[float64]map[float32]float32 и t1, t2 соответственно дает правильный результат.

В чем может быть причина этого странного поведения?

Ответы [ 3 ]

8 голосов
/ 07 апреля 2020

32-битное число с плавающей запятой имеет 23-битную мантиссу с неявным предшествующим старшему 1-битному. Таким образом, максимальное значение, представляемое мантиссой, равно 2²⁴-1 = 16777215. Другими словами, только целые числа в диапазоне от -16777215 до 16777215 могут быть точно в виде 32-разрядного числа с плавающей запятой.

Ваши два значения 1586238540 и 1586238600 находятся за пределами этого диапазона и оба усечены до одного и того же значения 1586238592. И именно это усеченное значение используется в качестве ключа для карты.

2 голосов
/ 07 апреля 2020

https://play.golang.org/p/Fx78BbmnXIE, 1586238540 и 1586238600 одинаковы в памяти

1 голос
/ 07 апреля 2020

если вы добавите это к своему коду

fmt.Println(t1)
fmt.Println(t2)

, вы увидите 1.5862386e+09 как результат для обоих, потому что значение слишком велико для float32. с float64 вы увидите правильное значение, напечатанное

1.58623854e+09
1.5862386e+09

для получения дополнительной информации wikipedia

...