'Getting different output for slight variation in input for unicode.IsNumber() function in Go

Why does unicode.IsNumber(rune(truncfloat)) returns false some cases?

For 55.3 output is true For 58.3 output is false

Below is my code:

package main

import (
    "fmt"
    "unicode"
)

func main() {
    var truncint int
    var truncfloat float64

    fmt.Printf("Enter a floating point number: ")
    num, err := fmt.Scan(&truncfloat)

    if unicode.IsNumber(rune(truncfloat)) {
        truncint = int(truncfloat)
        fmt.Printf("Trucated number is: %d", truncint)
    } else {
        fmt.Printf("Recieved %d numbers, Error: %s", num, err)
    }
}

Following are test cases with Execution output:

PS C:\learngo> .\trunc.exe
Enter a floating point number: 58.3
Recieved 1 numbers, Error: %!s(<nil>)
PS C:\learngo> .\trunc.exe
Enter a floating point number: 55.3
Trucated number is: 55


Solution 1:[1]

The function unicode.IsNumber() expects a rune, such as '0' or '9'. While you do indeed pass a rune, the contained value is just whatever code point 55 and 58 map to. You will find out which by adding:

fmt.Println(string(rune(truncfloat)))

This will print 7 for 55 and : for 58. : is not a number, so your check fails.

What you actually want to do is to cast to int instead of rune (because you care about the integer value of the result, not its Unicode code point) and do your number check before the cast instead (since int cannot hold values which are not a number (NaN)).

if math.IsNaN(truncfloat) {
    fmt.Println("Entered float is not a number")
    return
}
if truncfloat > math.MaxInt || truncfloat < math.MinInt {
    fmt.Println("Entered float is outside of int range")
    return
}
truncint = int(truncfloat)
fmt.Printf("Truncated number is: %d", truncint)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1