Jump to content

Test integerness: Difference between revisions

Add Go solution
(→‎{{header|Ruby}}: Use simpler syntax on last example)
(Add Go solution)
Line 5:
To be clear, we're not talking about whether the number is stored with the specific data type for integers, but instead we want to test whether there exists an integer with the exact same value. In other words, we want to test for integerness in the mathematical sense, not as a data type.
 
=={{header|Go}}==
<lang go>package main
 
import (
"fmt"
"math"
"math/big"
"reflect"
"strings"
"unsafe"
)
 
func FloatIsInt(f float64) bool { return f == math.Trunc(f) }
func ComplexIsInt(c complex128) bool { return imag(c) == 0 && FloatIsInt(real(c)) }
 
// Usually just the above two would be all that is used, but if it is
// desired to have a single function that can test any arbitrary type,
// including the standard math/big types, user defined types based on an
// integer, float, or complex builtin types, or user defined types that
// have an IsInt() method, then reflection can be used.
 
type hasIsInt interface {
IsInt() bool
}
 
var bigIntT = reflect.TypeOf((*big.Int)(nil))
 
func IsInt(i interface{}) bool {
if ci, ok := i.(hasIsInt); ok {
// Handles things like *big.Rat
return ci.IsInt()
}
switch v := reflect.ValueOf(i); v.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16,
reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16,
reflect.Uint32, reflect.Uint64, reflect.Uintptr:
// Built-in types and any custom type based on them
return true
case reflect.Float32, reflect.Float64:
// Built-in floats and anything based on them
return FloatIsInt(v.Float())
case reflect.Complex64, reflect.Complex128:
// Built-in complexes and anything based on them
return ComplexIsInt(v.Complex())
case reflect.String:
// Could also do strconv.ParseFloat then FloatIsInt but
// big.Rat handles everything ParseFloat can plus more.
// Note, there is no strconv.ParseComplex.
if r, ok := new(big.Rat).SetString(v.String()); ok {
return r.IsInt()
}
case reflect.Ptr:
// Special case for math/big.Int
if v.Type() == bigIntT {
return true
}
}
return false
}
 
// The rest is just demonstration and display
 
type intbased int16
type complexbased complex64
type customIntegerType struct {
// Anything that stores or represents a sub-set
// of integer values in any way desired.
}
 
func (customIntegerType) IsInt() bool { return true }
func (customIntegerType) String() string { return "<…>" }
 
func main() {
hdr := fmt.Sprintf("%27s %-6s %s\n", "Input", "IsInt", "Type")
show2 := func(t bool, i interface{}, args ...interface{}) {
istr := fmt.Sprint(i)
fmt.Printf("%27s %-6t %T ", istr, t, i)
fmt.Println(args...)
}
show := func(i interface{}, args ...interface{}) {
show2(IsInt(i), i, args...)
}
 
fmt.Print("Using FloatIsInt with float64:\n", hdr)
for _, f := range []float64{
0, -2, -2.000000000000001, 10. / 2, 22. / 3,
math.Pi,
math.MinInt64, math.MaxUint64,
math.SmallestNonzeroFloat64, math.MaxFloat64,
math.NaN(), math.Inf(1), math.Inf(-1),
} {
show2(FloatIsInt(f), f)
}
 
fmt.Print("\nUsing ComplexIsInt with complex128:\n", hdr)
for _, c := range []complex128{
3, 1i, 0i, 3.4,
} {
show2(ComplexIsInt(c), c)
}
 
fmt.Println("\nUsing reflection:")
fmt.Print(hdr)
show("hello")
show(math.MaxFloat64)
show("9e100")
show("(4+0i)", "(complex strings not parsed)")
show(4 + 0i)
show(rune('§'), "or rune")
show(byte('A'), "or byte")
var t1 intbased = 5200
var t2a, t2b complexbased = 5 + 0i, 5 + 1i
show(t1)
show(t2a)
show(t2b)
x := uintptr(unsafe.Pointer(&t2b))
show(x)
show(math.MinInt32)
show(uint64(math.MaxUint64))
b, _ := new(big.Int).SetString(strings.Repeat("9", 25), 0)
show(b)
r, _ := new(big.Rat).SetString("2/3")
show(r)
r.SetFrac(b, new(big.Int).SetInt64(9))
show(r)
show("12345/5")
show(new(customIntegerType))
}</lang>
{{out}}
<pre>
Using FloatIsInt with float64:
Input IsInt Type
0 true float64
-2 true float64
-2.000000000000001 false float64
5 true float64
7.333333333333333 false float64
3.141592653589793 false float64
-9.223372036854776e+18 true float64
1.8446744073709552e+19 true float64
5e-324 false float64
1.7976931348623157e+308 true float64
NaN false float64
+Inf true float64
-Inf true float64
 
Using ComplexIsInt with complex128:
Input IsInt Type
(3+0i) true complex128
(0+1i) false complex128
(0+0i) true complex128
(3.4+0i) false complex128
 
Using reflection:
Input IsInt Type
hello false string
1.7976931348623157e+308 true float64
9e100 true string
(4+0i) false string (complex strings not parsed)
(4+0i) true complex128
167 true int32 or rune
65 true uint8 or byte
5200 true main.intbased
(5+0i) true main.complexbased
(5+1i) false main.complexbased
34367302872 true uintptr
-2147483648 true int
18446744073709551615 true uint64
9999999999999999999999999 true *big.Int
2/3 false *big.Rat
1111111111111111111111111/1 true *big.Rat
12345/5 true string
<…> true *main.customIntegerType
</pre>
 
=={{header|J}}==
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.