Почему результат Go такой же? - PullRequest
0 голосов
/ 16 января 2019

Когда я просматривал проект Golang, я нашел такой код, now - метка времени Unix. Вызывайте эту функцию раз в секунду:

//main.go
func PrevSlot(now int64) int64 {
    // now = time.Now().Unix()
    var blockInterval = int64(10)

    result := int64((now-1)/blockInterval) * blockInterval // why result is same ?
    plog.Println("PrevSlot:", int64(result), int64((now-1)/blockInterval), now)
    return result
}


func main() {
    ticker := time.NewTicker(1 * time.Second)
    for {
        <-ticker.C

        now := time.Now().Unix()
        PrevSlot(now)
    }

}

Выход:

2019-01-16 10:58:31.668597 I | dpos.go: PrevSlot: 1547607510 154760751 1547607511
2019-01-16 10:58:32.668649 I | dpos.go: PrevSlot: 1547607510 154760751 1547607512
2019-01-16 10:58:33.668568 I | dpos.go: PrevSlot: 1547607510 154760751 1547607513
2019-01-16 10:58:34.668572 I | dpos.go: PrevSlot: 1547607510 154760751 1547607514
2019-01-16 10:58:35.668547 I | dpos.go: PrevSlot: 1547607510 154760751 1547607515

Результат тот же. Почему это так, по какому принципу?

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Ваша проблема здесь:

result := int64((now-1)/blockInterval) * blockInterval

time.Now().Unix() возвращает текущее время Unix в секундах . Таким образом, для последовательных итераций time.Now().Unix() будет:

1257894001
1257894002
1257894003

Но в своей функции вы вычитаете 1, а затем делите на десять, поэтому каждое из вышеперечисленных становится следующим, поскольку дробная часть отбрасывается.

125789400
125789400
125789400

Затем, когда вы умножите на blockInterval (10), все они станут:

1257894000
1257894000
1257894000

Итак, result заканчивается тем же. Если вы дадите ему работать дольше десяти секунд, вы увидите result изменение через 10 секунд:

https://play.golang.org/p/LgPtHwjwlC1

0 голосов
/ 16 января 2019

На самом деле,

int64((now - 1)/blockInterval * blockInterval

не возвращает один и тот же результат все время.Вы заметите, что он меняется каждые 10 секунд.

Это вызвано целочисленным делением в Go.Если вы применяете целочисленное деление к любым двум числам, то дробная часть результата (остаток) отбрасывается.Например, int(12 / 10) = 1.В вашем конкретном случае - при делении на десять код сбрасывает остатки с 1 до 9 и увеличивает значение только при переходе к следующим 10.

Если вы хотите повысить точность вашегооперации, то вы можете форсировать деление с плавающей точкой, как это float64(12)/float64(10).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...