Test integerness: Difference between revisions
Content added Content deleted
Catskill549 (talk | contribs) |
Thundergnat (talk | contribs) (Rename Perl 6 -> Raku, alphabetize, minor clean-up) |
||
Line 150: | Line 150: | ||
+1.2345678901234567890123400000000000e +23_+0.0000000000000000000000000000000000e +0 is integral |
+1.2345678901234567890123400000000000e +23_+0.0000000000000000000000000000000000e +0 is integral |
||
</pre> |
</pre> |
||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
<lang AWK> |
<lang AWK> |
||
Line 261: | Line 262: | ||
</pre> |
</pre> |
||
=={{header|C |
=={{header|C sharp|C#}}== |
||
<lang cpp> |
|||
#include <complex> |
|||
#include <math.h> |
|||
#include <iostream> |
|||
template<class Type> |
|||
struct Precision |
|||
{ |
|||
public: |
|||
static Type GetEps() |
|||
{ |
|||
return eps; |
|||
} |
|||
static void SetEps(Type e) |
|||
{ |
|||
eps = e; |
|||
} |
|||
private: |
|||
static Type eps; |
|||
}; |
|||
template<class Type> Type Precision<Type>::eps = static_cast<Type>(1E-7); |
|||
template<class DigType> |
|||
bool IsDoubleEqual(DigType d1, DigType d2) |
|||
{ |
|||
return (fabs(d1 - d2) < Precision<DigType>::GetEps()); |
|||
} |
|||
template<class DigType> |
|||
DigType IntegerPart(DigType value) |
|||
{ |
|||
return (value > 0) ? floor(value) : ceil(value); |
|||
} |
|||
template<class DigType> |
|||
DigType FractionPart(DigType value) |
|||
{ |
|||
return fabs(IntegerPart<DigType>(value) - value); |
|||
} |
|||
template<class Type> |
|||
bool IsInteger(const Type& value) |
|||
{ |
|||
return false; |
|||
} |
|||
#define GEN_CHECK_INTEGER(type) \ |
|||
template<> \ |
|||
bool IsInteger<type>(const type& value) \ |
|||
{ \ |
|||
return true; \ |
|||
} |
|||
#define GEN_CHECK_CMPL_INTEGER(type) \ |
|||
template<> \ |
|||
bool IsInteger<std::complex<type> >(const std::complex<type>& value) \ |
|||
{ \ |
|||
type zero = type(); \ |
|||
return value.imag() == zero; \ |
|||
} |
|||
#define GEN_CHECK_REAL(type) \ |
|||
template<> \ |
|||
bool IsInteger<type>(const type& value) \ |
|||
{ \ |
|||
type zero = type(); \ |
|||
return IsDoubleEqual<type>(FractionPart<type>(value), zero); \ |
|||
} |
|||
#define GEN_CHECK_CMPL_REAL(type) \ |
|||
template<> \ |
|||
bool IsInteger<std::complex<type> >(const std::complex<type>& value) \ |
|||
{ \ |
|||
type zero = type(); \ |
|||
return IsDoubleEqual<type>(value.imag(), zero); \ |
|||
} |
|||
#define GEN_INTEGER(type) \ |
|||
GEN_CHECK_INTEGER(type) \ |
|||
GEN_CHECK_CMPL_INTEGER(type) |
|||
#define GEN_REAL(type) \ |
|||
GEN_CHECK_REAL(type) \ |
|||
GEN_CHECK_CMPL_REAL(type) |
|||
GEN_INTEGER(char) |
|||
GEN_INTEGER(unsigned char) |
|||
GEN_INTEGER(short) |
|||
GEN_INTEGER(unsigned short) |
|||
GEN_INTEGER(int) |
|||
GEN_INTEGER(unsigned int) |
|||
GEN_INTEGER(long) |
|||
GEN_INTEGER(unsigned long) |
|||
GEN_INTEGER(long long) |
|||
GEN_INTEGER(unsigned long long) |
|||
GEN_REAL(float) |
|||
GEN_REAL(double) |
|||
GEN_REAL(long double) |
|||
template<class Type> |
|||
inline void TestValue(const Type& value) |
|||
{ |
|||
std::cout << "Value: " << value << " of type: " << typeid(Type).name() << " is integer - " << std::boolalpha << IsInteger(value) << std::endl; |
|||
} |
|||
int main() |
|||
{ |
|||
char c = -100; |
|||
unsigned char uc = 200; |
|||
short s = c; |
|||
unsigned short us = uc; |
|||
int i = s; |
|||
unsigned int ui = us; |
|||
long long ll = i; |
|||
unsigned long long ull = ui; |
|||
std::complex<unsigned int> ci1(2, 0); |
|||
std::complex<int> ci2(2, 4); |
|||
std::complex<int> ci3(-2, 4); |
|||
std::complex<unsigned short> cs1(2, 0); |
|||
std::complex<short> cs2(2, 4); |
|||
std::complex<short> cs3(-2, 4); |
|||
std::complex<double> cd1(2, 0); |
|||
std::complex<float> cf1(2, 4); |
|||
std::complex<double> cd2(-2, 4); |
|||
float f1 = 1.0; |
|||
float f2 = -2.0; |
|||
float f3 = -2.4f; |
|||
float f4 = 1.23e-5f; |
|||
float f5 = 1.23e-10f; |
|||
double d1 = f5; |
|||
TestValue(c); |
|||
TestValue(uc); |
|||
TestValue(s); |
|||
TestValue(us); |
|||
TestValue(i); |
|||
TestValue(ui); |
|||
TestValue(ll); |
|||
TestValue(ull); |
|||
TestValue(ci1); |
|||
TestValue(ci2); |
|||
TestValue(ci3); |
|||
TestValue(cs1); |
|||
TestValue(cs2); |
|||
TestValue(cs3); |
|||
TestValue(cd1); |
|||
TestValue(cd2); |
|||
TestValue(cf1); |
|||
TestValue(f1); |
|||
TestValue(f2); |
|||
TestValue(f3); |
|||
TestValue(f4); |
|||
TestValue(f5); |
|||
std::cout << "Set float precision: 1e-15f\n"; |
|||
Precision<float>::SetEps(1e-15f); |
|||
TestValue(f5); |
|||
TestValue(d1); |
|||
return 0; |
|||
} |
|||
</lang> |
|||
{{out}} |
|||
<pre> |
|||
Value: Ь of type: char is integer - true |
|||
Value: ╚ of type: unsigned char is integer - true |
|||
Value: -100 of type: short is integer - true |
|||
Value: 200 of type: unsigned short is integer - true |
|||
Value: -100 of type: int is integer - true |
|||
Value: 200 of type: unsigned int is integer - true |
|||
Value: -100 of type: __int64 is integer - true |
|||
Value: 200 of type: unsigned __int64 is integer - true |
|||
Value: (2,0) of type: class std::complex<unsigned int> is integer - true |
|||
Value: (2,4) of type: class std::complex<int> is integer - false |
|||
Value: (-2,4) of type: class std::complex<int> is integer - false |
|||
Value: (2,0) of type: class std::complex<unsigned short> is integer - true |
|||
Value: (2,4) of type: class std::complex<short> is integer - false |
|||
Value: (-2,4) of type: class std::complex<short> is integer - false |
|||
Value: (2,0) of type: class std::complex<double> is integer - true |
|||
Value: (-2,4) of type: class std::complex<double> is integer - false |
|||
Value: (2,4) of type: class std::complex<float> is integer - false |
|||
Value: 1 of type: float is integer - true |
|||
Value: -2 of type: float is integer - true |
|||
Value: -2.4 of type: float is integer - false |
|||
Value: 1.23e-05 of type: float is integer - false |
|||
Value: 1.23e-10 of type: float is integer - true |
|||
Set float precision: 1e-15f |
|||
Value: 1.23e-10 of type: float is integer - false |
|||
Value: 1.23e-10 of type: double is integer - true |
|||
</pre> |
|||
=={{header|C#}}== |
|||
Line 684: | Line 483: | ||
Another test < Y /N > . . . |
Another test < Y /N > . . . |
||
</pre> |
|||
=={{header|C++}}== |
|||
<lang cpp> |
|||
#include <complex> |
|||
#include <math.h> |
|||
#include <iostream> |
|||
template<class Type> |
|||
struct Precision |
|||
{ |
|||
public: |
|||
static Type GetEps() |
|||
{ |
|||
return eps; |
|||
} |
|||
static void SetEps(Type e) |
|||
{ |
|||
eps = e; |
|||
} |
|||
private: |
|||
static Type eps; |
|||
}; |
|||
template<class Type> Type Precision<Type>::eps = static_cast<Type>(1E-7); |
|||
template<class DigType> |
|||
bool IsDoubleEqual(DigType d1, DigType d2) |
|||
{ |
|||
return (fabs(d1 - d2) < Precision<DigType>::GetEps()); |
|||
} |
|||
template<class DigType> |
|||
DigType IntegerPart(DigType value) |
|||
{ |
|||
return (value > 0) ? floor(value) : ceil(value); |
|||
} |
|||
template<class DigType> |
|||
DigType FractionPart(DigType value) |
|||
{ |
|||
return fabs(IntegerPart<DigType>(value) - value); |
|||
} |
|||
template<class Type> |
|||
bool IsInteger(const Type& value) |
|||
{ |
|||
return false; |
|||
} |
|||
#define GEN_CHECK_INTEGER(type) \ |
|||
template<> \ |
|||
bool IsInteger<type>(const type& value) \ |
|||
{ \ |
|||
return true; \ |
|||
} |
|||
#define GEN_CHECK_CMPL_INTEGER(type) \ |
|||
template<> \ |
|||
bool IsInteger<std::complex<type> >(const std::complex<type>& value) \ |
|||
{ \ |
|||
type zero = type(); \ |
|||
return value.imag() == zero; \ |
|||
} |
|||
#define GEN_CHECK_REAL(type) \ |
|||
template<> \ |
|||
bool IsInteger<type>(const type& value) \ |
|||
{ \ |
|||
type zero = type(); \ |
|||
return IsDoubleEqual<type>(FractionPart<type>(value), zero); \ |
|||
} |
|||
#define GEN_CHECK_CMPL_REAL(type) \ |
|||
template<> \ |
|||
bool IsInteger<std::complex<type> >(const std::complex<type>& value) \ |
|||
{ \ |
|||
type zero = type(); \ |
|||
return IsDoubleEqual<type>(value.imag(), zero); \ |
|||
} |
|||
#define GEN_INTEGER(type) \ |
|||
GEN_CHECK_INTEGER(type) \ |
|||
GEN_CHECK_CMPL_INTEGER(type) |
|||
#define GEN_REAL(type) \ |
|||
GEN_CHECK_REAL(type) \ |
|||
GEN_CHECK_CMPL_REAL(type) |
|||
GEN_INTEGER(char) |
|||
GEN_INTEGER(unsigned char) |
|||
GEN_INTEGER(short) |
|||
GEN_INTEGER(unsigned short) |
|||
GEN_INTEGER(int) |
|||
GEN_INTEGER(unsigned int) |
|||
GEN_INTEGER(long) |
|||
GEN_INTEGER(unsigned long) |
|||
GEN_INTEGER(long long) |
|||
GEN_INTEGER(unsigned long long) |
|||
GEN_REAL(float) |
|||
GEN_REAL(double) |
|||
GEN_REAL(long double) |
|||
template<class Type> |
|||
inline void TestValue(const Type& value) |
|||
{ |
|||
std::cout << "Value: " << value << " of type: " << typeid(Type).name() << " is integer - " << std::boolalpha << IsInteger(value) << std::endl; |
|||
} |
|||
int main() |
|||
{ |
|||
char c = -100; |
|||
unsigned char uc = 200; |
|||
short s = c; |
|||
unsigned short us = uc; |
|||
int i = s; |
|||
unsigned int ui = us; |
|||
long long ll = i; |
|||
unsigned long long ull = ui; |
|||
std::complex<unsigned int> ci1(2, 0); |
|||
std::complex<int> ci2(2, 4); |
|||
std::complex<int> ci3(-2, 4); |
|||
std::complex<unsigned short> cs1(2, 0); |
|||
std::complex<short> cs2(2, 4); |
|||
std::complex<short> cs3(-2, 4); |
|||
std::complex<double> cd1(2, 0); |
|||
std::complex<float> cf1(2, 4); |
|||
std::complex<double> cd2(-2, 4); |
|||
float f1 = 1.0; |
|||
float f2 = -2.0; |
|||
float f3 = -2.4f; |
|||
float f4 = 1.23e-5f; |
|||
float f5 = 1.23e-10f; |
|||
double d1 = f5; |
|||
TestValue(c); |
|||
TestValue(uc); |
|||
TestValue(s); |
|||
TestValue(us); |
|||
TestValue(i); |
|||
TestValue(ui); |
|||
TestValue(ll); |
|||
TestValue(ull); |
|||
TestValue(ci1); |
|||
TestValue(ci2); |
|||
TestValue(ci3); |
|||
TestValue(cs1); |
|||
TestValue(cs2); |
|||
TestValue(cs3); |
|||
TestValue(cd1); |
|||
TestValue(cd2); |
|||
TestValue(cf1); |
|||
TestValue(f1); |
|||
TestValue(f2); |
|||
TestValue(f3); |
|||
TestValue(f4); |
|||
TestValue(f5); |
|||
std::cout << "Set float precision: 1e-15f\n"; |
|||
Precision<float>::SetEps(1e-15f); |
|||
TestValue(f5); |
|||
TestValue(d1); |
|||
return 0; |
|||
} |
|||
</lang> |
|||
{{out}} |
|||
<pre> |
|||
Value: Ь of type: char is integer - true |
|||
Value: ╚ of type: unsigned char is integer - true |
|||
Value: -100 of type: short is integer - true |
|||
Value: 200 of type: unsigned short is integer - true |
|||
Value: -100 of type: int is integer - true |
|||
Value: 200 of type: unsigned int is integer - true |
|||
Value: -100 of type: __int64 is integer - true |
|||
Value: 200 of type: unsigned __int64 is integer - true |
|||
Value: (2,0) of type: class std::complex<unsigned int> is integer - true |
|||
Value: (2,4) of type: class std::complex<int> is integer - false |
|||
Value: (-2,4) of type: class std::complex<int> is integer - false |
|||
Value: (2,0) of type: class std::complex<unsigned short> is integer - true |
|||
Value: (2,4) of type: class std::complex<short> is integer - false |
|||
Value: (-2,4) of type: class std::complex<short> is integer - false |
|||
Value: (2,0) of type: class std::complex<double> is integer - true |
|||
Value: (-2,4) of type: class std::complex<double> is integer - false |
|||
Value: (2,4) of type: class std::complex<float> is integer - false |
|||
Value: 1 of type: float is integer - true |
|||
Value: -2 of type: float is integer - true |
|||
Value: -2.4 of type: float is integer - false |
|||
Value: 1.23e-05 of type: float is integer - false |
|||
Value: 1.23e-10 of type: float is integer - true |
|||
Set float precision: 1e-15f |
|||
Value: 1.23e-10 of type: float is integer - false |
|||
Value: 1.23e-10 of type: double is integer - true |
|||
</pre> |
</pre> |
||
Line 1,646: | Line 1,647: | ||
String! false |
String! false |
||
true false</pre> |
true false</pre> |
||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
|||
The built-in function IntegerQ performs the required test |
|||
<lang Mathematica>IntegerQ /@ {E, 2.4, 7, 9/2}</lang> |
|||
{{out}}<pre>{False,False,True,False}</pre> |
|||
=={{header|ooRexx}}== |
=={{header|ooRexx}}== |
||
Line 1,729: | Line 1,735: | ||
3+0i is an integer</pre> |
3+0i is an integer</pre> |
||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
|||
The built-in function IntegerQ performs the required test |
|||
<lang Mathematica>IntegerQ /@ {E, 2.4, 7, 9/2}</lang> |
|||
{{out}}<pre>{False,False,True,False}</pre> |
|||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
Line 1,771: | Line 1,773: | ||
4-3i is NOT an integer |
4-3i is NOT an integer |
||
5.6 is NOT an integer |
5.6 is NOT an integer |
||
</pre> |
|||
=={{header|Perl 6}}== |
|||
In Perl 6, all numeric types have a method called <tt>narrow</tt>, which returns an object with the same value but of the most appropriate type. So we can just check if ''that'' object is an <tt>Int</tt>. This works even with floats with large exponents, because the <tt>Int</tt> type supports arbitrarily large integers. |
|||
For the extra credit task, we can add another multi candidate that checks the distance between the number and it's nearest integer, but then we'll have to handle complex numbers specially. |
|||
<lang perl6>multi is-int ($n) { $n.narrow ~~ Int } |
|||
multi is-int ($n, :$tolerance!) { |
|||
abs($n.round - $n) <= $tolerance |
|||
} |
|||
multi is-int (Complex $n, :$tolerance!) { |
|||
is-int($n.re, :$tolerance) && abs($n.im) < $tolerance |
|||
} |
|||
# Testing: |
|||
for 25.000000, 24.999999, 25.000100, -2.1e120, -5e-2, Inf, NaN, 5.0+0.0i, 5-5i { |
|||
printf "%-7s %-9s %-5s %-5s\n", .^name, $_, |
|||
is-int($_), |
|||
is-int($_, :tolerance<0.00001>); |
|||
}</lang> |
|||
{{out}} |
|||
<pre> |
|||
Rat 25 True True |
|||
Rat 24.999999 False True |
|||
Rat 25.0001 False False |
|||
Num -2.1e+120 True True |
|||
Num -0.05 False False |
|||
Num Inf False False |
|||
Num NaN False False |
|||
Complex 5+0i True True |
|||
Complex 5-5i False False |
|||
</pre> |
</pre> |
||
Line 1,978: | Line 1,943: | ||
</lang> |
</lang> |
||
All tests pass. |
All tests pass. |
||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
In Perl 6, all numeric types have a method called <tt>narrow</tt>, which returns an object with the same value but of the most appropriate type. So we can just check if ''that'' object is an <tt>Int</tt>. This works even with floats with large exponents, because the <tt>Int</tt> type supports arbitrarily large integers. |
|||
For the extra credit task, we can add another multi candidate that checks the distance between the number and it's nearest integer, but then we'll have to handle complex numbers specially. |
|||
<lang perl6>multi is-int ($n) { $n.narrow ~~ Int } |
|||
multi is-int ($n, :$tolerance!) { |
|||
abs($n.round - $n) <= $tolerance |
|||
} |
|||
multi is-int (Complex $n, :$tolerance!) { |
|||
is-int($n.re, :$tolerance) && abs($n.im) < $tolerance |
|||
} |
|||
# Testing: |
|||
for 25.000000, 24.999999, 25.000100, -2.1e120, -5e-2, Inf, NaN, 5.0+0.0i, 5-5i { |
|||
printf "%-7s %-9s %-5s %-5s\n", .^name, $_, |
|||
is-int($_), |
|||
is-int($_, :tolerance<0.00001>); |
|||
}</lang> |
|||
{{out}} |
|||
<pre> |
|||
Rat 25 True True |
|||
Rat 24.999999 False True |
|||
Rat 25.0001 False False |
|||
Num -2.1e+120 True True |
|||
Num -0.05 False False |
|||
Num Inf False False |
|||
Num NaN False False |
|||
Complex 5+0i True True |
|||
Complex 5-5i False False |
|||
</pre> |
|||
=={{header|REXX}}== |
=={{header|REXX}}== |