go-playground / validator

:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving
MIT License
16.14k stars 1.29k forks source link

add floating-point precision to four decimal places #1145

Closed ahaooahaz closed 11 months ago

ahaooahaz commented 11 months ago

Fixes Or Enhances

Make sure that you've checked the boxes below before you submit PR:

@go-playground/validator-maintainers

coveralls commented 11 months ago

Coverage Status

coverage: 74.001% (+0.01%) from 73.991% when pulling b71b5017a60fcbb4683e94e9edf559b72348c6d8 on ahaooahaz:feature/float into 5bf55dc757cad229e8297d42640ec036e2360df7 on go-playground:master.

deankarn commented 11 months ago

@ahaooahaz Thank you for the PR, but I already have one up that should correct the issue without truncating the decimal precision https://github.com/go-playground/validator/pull/1146

Will try to get it merged and published after work.

ahaooahaz commented 11 months ago

@deankarn Floating-point numbers that lose precision should be a problem caused by reflection, I think the problem appears in validator.go:77 current.Field(f.idx), if use current.Field(f.idx).Float() it already lose precision ,I saw your code modify the 32-bit and 64-bit tool functions from string to float respectively, but this is not the actual cause of the problem

deankarn commented 11 months ago

@ahaooahaz there is actually no problem per se.

This is a floating point precision thing and because the float32 is returned as a float64 it's actuating gaining precision.

Here's why my other PR fixes the issue without number truncation which can introduce other issues, especially where the code was implemented. The parsing code has been updated using asFloat32 and asFloat64 making it now behave identically to reflect.Float() function which both check the bit precision aka float32 vs float64

func asFloat64(param string) float64 {
    i, _ := strconv.ParseFloat(param, 64)
    return i
}

func asFloat32(param string) float64 {
    i, _ := strconv.ParseFloat(param, 32)
    return i
}

func main() {

    f32 := float32(0.1)
    f64 := float64(0.1)

    fmt.Println(float64(f32), reflect.ValueOf(f32).Float(), asFloat32("0.1"))
    fmt.Println(f64, reflect.ValueOf(f64).Float(), asFloat64("0.1"))
        //
    // output
    //
    // 0.10000000149011612 0.10000000149011612 0.10000000149011612
    // 0.1 0.1 0.1
}
ahaooahaz commented 11 months ago

@deankarn ohhh, I get it, GREAT WORKS!!