Go результат выполнения кода в локальной среде не совпадает с запуском в go play - PullRequest
1 голос
/ 28 февраля 2020

Я использую Go для реализации алгоритма, описанного ниже:

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

Мой код указан ниже:

import (
    "testing"
)

func findBySum(arr []int) int {

    result := 0
    sum := [32]int{}

    for i := 0; i < 32; i++ {
        for _, v := range arr {
            sum[i] += (v >> uint(i)) & 0x1
        }
        sum[i] %= 3
        sum[i] <<= uint(i)
        result |= sum[i]
    }

    return result
}

func TestThree(t *testing.T) {
    // except one nubmer,all other number appear three times
    a1 := []int{11, 222, 444, 444, 222, 11, 11, 17, -123, 222, -123, 444, -123}  // unqiue number is 17
    a2 := []int{11, 222, 444, 444, 222, 11, 11, -17, -123, 222, -123, 444, -123} // unque number is -17
    t.Log(findBySum(a1))
    t.Log(findBySum(a2))
}

Однако я обнаружил, что результат выполнения в моем P C неверен, и тот же код работает в https://play.golang.org/p/hEseLZVL617 правильно, я не знаю почему.

Результат в моем P C:
The result in my PC is wrong

Результат в https://play.golang.org/p/hEseLZVL617:
enter image description here

Как мы видим, когда уникальный номер положительный оба результата верны, но когда уникальное число отрицательное, результат в моем P C неверный, а результат в сети правильный.

Я думаю, что это как-то связано с битовыми операциями в моем код, но я не могу найти причину root.

Я использовал IDEA 2019.1.1 и мою версию Golang, указанную ниже:
enter image description here

Я не знаю, почему тот же код с Он отлично работает в Интернете и не работает в моем местном P C, кто-нибудь может мне помочь анализ этого? Заранее спасибо!

1 Ответ

2 голосов
/ 28 февраля 2020

Размер int зависит от платформы, он может быть 32-разрядным и 64-разрядным. На игровой площадке Go она 32-разрядная, на локальном компьютере - 64-разрядная.

Если мы изменим ваш пример на использование int64 вместо int, результат будет таким же, Go Детская площадка тоже:

func findBySum(arr []int64) int64 {

    result := int64(0)
    sum := [32]int64{}

    for i := int64(0); i < 32; i++ {
        for _, v := range arr {
            sum[i] += (v >> uint64(i)) & 0x1
        }
        sum[i] %= 3
        sum[i] <<= uint(i)
        result |= sum[i]
    }

    return result
}

func TestThree(t *testing.T) {
    // except one nubmer,all other number appear three times
    a1 := []int64{11, 222, 444, 444, 222, 11, 11, 17, -123, 222, -123, 444, -123}  // unqiue number is 17
    a2 := []int64{11, 222, 444, 444, 222, 11, 11, -17, -123, 222, -123, 444, -123} // unque number is -17
    t.Log(findBySum(a1))
    t.Log(findBySum(a2))
}

Вы выполняете побитовые операции, которые принимают 32-битный целочисленный размер. Чтобы получить правильные результаты локально (где ваша архитектура и, следовательно, размер int и uint равен 64-bit), измените все int s на int32 и uint на uint32:

func findBySum(arr []int32) int32 {

    result := int32(0)
    sum := [32]int32{}

    for i := int32(0); i < 32; i++ {
        for _, v := range arr {
            sum[i] += (v >> uint32(i)) & 0x1
        }
        sum[i] %= 3
        sum[i] <<= uint(i)
        result |= sum[i]
    }

    return result
}

func TestThree(t *testing.T) {
    // except one nubmer,all other number appear three times
    a1 := []int32{11, 222, 444, 444, 222, 11, 11, 17, -123, 222, -123, 444, -123}  // unqiue number is 17
    a2 := []int32{11, 222, 444, 444, 222, 11, 11, -17, -123, 222, -123, 444, -123} // unque number is -17
    t.Log(findBySum(a1))
    t.Log(findBySum(a2))
}

Урок: если вы выполняете вычисления, результат которых зависит от размера представления, всегда будьте явными и используйте числа фиксированного размера, такие как int32, int64, uint32, uint64.

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