在golang中,如何通过将float转换为整数来解决问题?

In golang, how could I solve the issue by converting float to integer?

提问人:Luke 提问时间:9/20/2023 更新时间:9/20/2023 访问量:109

问:

有一些关于在 golang 中排序的存储桶的代码。

但是,我遇到了关于索引超出范围 [10] 且长度为 10 的恐慌。

我发现有一些问题。因为应该是 9.99999999999。但是,将是 10。我是golang的新学习者。我不知道如何解决它。bucketIdx := int((v - minValue) / bucketSize)(v - minValue) / bucketSizeint((v - minValue) / bucketSize)

您可以在此处演示运行这些代码

这是源代码。

package main

import "fmt"

func bucketSort(array []float64) []float64 {
    // Determine minimum and maximum values
    minValue, maxValue := array[0], array[0]
    for _, v := range array {
        if v < minValue {
            minValue = v
        } else if v > maxValue {
            maxValue = v
        }
    }

    // Initialize buckets
    bucketSize := (maxValue - minValue) / 10
    bucketCount := 10
    buckets := make([][]float64, bucketCount)

    // Distribute elements into buckets
    for _, v := range array {
        bucketIdx := int((v - minValue) / bucketSize)
        buckets[bucketIdx] = append(buckets[bucketIdx], v)
    }

    // Sort buckets and place back into input array
    i := 0
    for _, bucket := range buckets {
        insertionSort(bucket)
        for _, v := range bucket {
            array[i] = v
            i++
        }
    }

    return array
}

func insertionSort(array []float64) {
    n := len(array)
    for i := 1; i < n; i++ {
        value := array[i]
        j := i - 1
        for j >= 0 && array[j] > value {
            array[j+1] = array[j]
            j--
        }
        array[j+1] = value
    }
}

func main() {
    array := []float64{0.897, 0.565, 0.656, 0.1234, 0.665, 0.3434}
    fmt.Println("Sorted Array: ", bucketSort(array))
}

感谢您的时间和考虑。

实际上,我尝试过使用数学。Floor() 来解决问题。但它仍然没有运行。

GO 浮点 类型转换

评论

0赞 icza 9/20/2023
如果要将浮点数转换为整数,请考虑使用舍入,因为类型转换采用整数部分(截断)。舍入:。当然可以四舍五入到任意单位,参见 Golang 四舍五入到最接近的 0.05int(f + 0.5)
1赞 Luke 9/20/2023
感谢您的回复,实际上,我不想使用舍入作为类型转换,我只想截断。如果我使用四舍五入,也许它会导致更大的索引。
0赞 Sarath Sadasivan Pillai 9/20/2023
这里的解决方法是使用 ,以确保 maxValue 本身仍将位于最后一个索引处。bucketSize := (maxValue - minValue + 1) / 10
0赞 Luke 9/20/2023
谢谢你,Sarath,你的解决方案很好。但是,我仍然很困惑为什么 int(9.9999999) 会变成 10。再次感谢你。
0赞 Sarath Sadasivan Pillai 9/20/2023
如果 bucketSize := (maxValue - minValue) / 10 , (maxValue - minValue) / bucketSize 将为 10 ( 或更多 ) 顺便说一句,浮点运算可能很棘手 stackoverflow.com/a/41878360/1898494

答:

3赞 chux - Reinstate Monica 9/20/2023 #1

在数学上,生成值 [0...10]。(含尾)bucketSize := (maxValue - minValue) / 10(v - minValue) / bucketSize

要生成值 [0...10)(注意表示非包容性),需要进行不同的计算。)


鉴于我们使用的是浮点数,因此值得考虑边缘情况。上面提到的 [0...10] 可能真的是 [略小于 0 ...略多于 10] 考虑到浮点数学及其各种舍入模式的有限精度。

为了避免特殊的边缘情况处理,而不是 1/10 的范围,请考虑 或 1/9。然后将索引计算移位 0.5。bucketSize1/(n-1)

n = 10 - 1
bucketSize := (maxValue - minValue) / n
...
//               v-- about 0 to about 9.0 -v   
bucketIdx := int((v - minValue) / bucketSize + 0.5)
//               ^-- about 0.5 to about 9.5 -----^
//           ^------ 0 to 9 ----------------------^

它确实使末端铲斗的平均人口是中间铲斗的一半,但我们不需要特殊的边缘测试。


当然,您可以采用安全可靠的方法:

bucketSize := (maxValue - minValue) / 10
...
bucketIdx := int((v - minValue) / bucketSize)
if bucketIdx >= 10 {
  bucketIdx := 10-1
}

如果溢出或下溢的任何部分,则需要额外考虑。(maxValue - minValue) / n

评论

0赞 Luke 9/20/2023
谢谢,我从你的代码中学到了很多东西。至于这个问题,你提供了一个很好的解决方案。但是,我想了解更多关于如何截断浮点数的信息。例如,我想int(1.999999999999999999999999999999)= 1,而不是2再次感谢你
2赞 chux - Reinstate Monica 9/20/2023
@Luke可以精确编码大约 2^64 个不同的值。1.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 代码采用该值,该值介于 2 个值之间:1.999999999999999779553953950749686919152736663818359375 (0x1.fffffffp+0) 和 2.0 之间,并选择较近的值:2.0。 是 2。float64float64int(2.0)
0赞 aka.nice 9/21/2023
您可以尝试较小的扰动(例如将 bucketSize 乘以 1.000001),而不是较大的扰动(将 bucketSize 乘以 10/9)。这只会带来少量的统计偏差......
1赞 chux - Reinstate Monica 9/21/2023
@Luke 有和没有 ,导致 0.0 到 10.0。同意?bucketSize := (maxValue - minValue) / 10;bucketSize = bucketSize * 1.0000001(v - minValue) / bucketSize
1赞 Luke 9/21/2023
@chux-恢复莫妮卡,我明白了,谢谢!