Determine if a string is numeric: Difference between revisions

Add ed example
(Added Z80 Assembly version)
(Add ed example)
 
(27 intermediate revisions by 18 users not shown)
Line 1,383:
You entered a number.</pre>
NB: While "99, rue de Rivoli" contains a number it is not a number entirely. The Val(v$) in this case would have stopped after it converted the "99" portion of the input, which when converted back to a string and compared to the original input would not result in an equality. 9E4 the program reads as an exponential value.
 
==={{header|SmallBASIC}}===
y = isnumber(s) returns true if s is a number or can be converted to a number.
<syntaxhighlight lang="qbasic">
a = 1.2345
b = "abc"
c = "-1.2345"
 
print isnumber(a)
print isnumber(b)
print isnumber(c)
</syntaxhighlight>
 
{{out}}
<pre>
1
0
1
</pre>
 
=={{header|Batch File}}==
Line 1,469 ⟶ 1,488:
'192.168.0.1' Not numeric
</pre>
 
=={{header|BQN}}==
<syntaxhighlight lang="bqn">IsNumeric ← 1∘•ParseFloat⎊0</syntaxhighlight>
 
=={{header|Bracmat}}==
Line 1,484 ⟶ 1,506:
80000000000:~/#
S</syntaxhighlight>
Bracmat doesn't do floating point computations (historical reason: the Acorn Risc Machine a.k.a. ARM processor in the Archimedes computer did not have an FPU), but theThe pattern <code>~/# (|"." (|? 0|`) (|~/#:>0)) (|(E|e) ~/#)</code> recognises string representations of floating point numbers.
<syntaxhighlight lang="bracmat">@("1.000-4E-10":~/# (|"." (|? 0|`) (|~/#:>0)) (|(E|e) ~/#))
F
Line 1,515 ⟶ 1,537:
S</syntaxhighlight>
 
Calculations with floating point numbers are delegated to UFP (Un-I-fancy-fied Floating Point, because it took me 30 years to dream up a viable way to do FP in Bracmat without breaking existing code) objects. An UFP object compiles and executes code that only handles C "doubles" and (multidimensional) arrays of such values.
To do computations with such "floating point strings" you would have to convert such strings to fractional representations first.
<syntaxhighlight lang="bracmat">(float2fraction=
integerPart decimalPart d1 dn exp sign
. @( !arg
: ~/#?integerPart
( &0:?decimalPart:?d1:?dn
| "."
[?d1
(|? 0|`)
( &0:?decimalPart
| ~/#?decimalPart:>0
)
[?dn
)
( &0:?exp
| (E|e) ~/#?exp
)
)
& ( !integerPart*(-1:?sign):>0:?integerPart
| 1:?sign
)
& !sign*(!integerPart+!decimalPart*10^(!d1+-1*!dn))*10^!exp
);
 
( out$float2fraction$"1.2"
& out$float2fraction$"1.02"
& out$float2fraction$"1.01"
& out$float2fraction$"10.01"
& out$float2fraction$"10.01e10"
& out$float2fraction$"10.01e1"
& out$float2fraction$"10.01e2"
& out$float2fraction$"10.01e-2"
& out$float2fraction$"-10.01e-2"
& out$float2fraction$"-10e-2"
& out$float2fraction$"0.000"
);
</syntaxhighlight>
{{out}}
<pre>6/5
51/50
101/100
1001/100
100100000000
1001/10
1001
1001/10000
-1001/10000
-1/10
0</pre>
 
=={{header|Burlesque}}==
Line 1,576 ⟶ 1,550:
 
<syntaxhighlight lang="c">#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
 
int isNumeric (const char * s)
bool isNumeric(const char *s) {
{
if (s == NULL || *s == '\0' || isspace(*s)) {
return 0false;
char * p;}
strtodchar (s, &*p);
strtod(s, &p);
return *p == '\0';
}</syntaxhighlight>
Line 1,617 ⟶ 1,593:
 
=={{header|C++}}==
{{trans|C}}<syntaxhighlight lang="cpp">#include <cctype>
#include <cstdlib>
 
bool isNumeric(const char *s) {
if (s == nullptr || *s == '\0' || std::isspace(*s)) {
return false;
}
char *p;
std::strtod(s, &p);
return *p == '\0';
}</syntaxhighlight>
 
Using stringstream:
<syntaxhighlight lang="cpp">#include <sstream> // for istringstream
Line 2,006 ⟶ 1,994:
 
=={{header|EasyLang}}==
<syntaxhighlight lang="text">func is_numeric a$ . r .
func is_numeric a$ .
h = number a$
r =h 1= -number errora$
# because every variable must be used
h = h
return 1 - error
.
for s$ in [ "abc" "21a" "1234" "-13" "7.65" ]
call if is_numeric s$ r= 1
print s$ & " is numeric"
if r = 1
else
print s$ & " is numeric"
print s$ & " is not numeric"
else
.
print s$ & " is not numeric"
.
.</syntaxhighlight>
 
=={{header|EchoLisp}}==
Line 2,031 ⟶ 2,020:
→ YES
</syntaxhighlight>
 
=={{header|Ed}}==
 
<syntaxhighlight lang="sed">
H
g/^([-+]?[0-9]*)(\.[0-9]+([eE][+-]?[0-9]+)?)?$/s//\1\2 is numeric/
v/numeric/s/.*/& is not numeric/
,p
Q
</syntaxhighlight>
 
{{out}}
 
<pre>$ cat string-numeric.ed | ed -GlEs string-numeric.input
Newline appended
56233 is numeric
-315 is numeric
1.36 is numeric
-5.126 is numeric
3.7E-05 is numeric
1.23BC is not numeric
5.6.3 is not numeric</pre>
 
=={{header|Elixir}}==
Line 2,047 ⟶ 2,058:
<pre>
["123", "-12.3", "-12e5", "+123"]
</pre>
 
=={{header|Emacs Lisp}}==
<syntaxhighlight lang="lisp">
(defun string-valid-number-p (str)
"Test if STR is a numeric string.
Eliminate strings with commas in them because ELisp numbers do
not contain commas. Then check if remaining strings would be
valid ELisp numbers if the quotation marks were removed."
(and
;; no comma in string, because ELisp numbers do not have commas
;; we need to eliminate any string with a comma, because the
;; numberp function below will not weed out commas
(not (string-match-p "," str))
;; no errors from numberp function testing if a number
(ignore-errors (numberp (read str)))))
 
 
</syntaxhighlight>
{{out}}
Below is ELisp code to test two lists. One is a list of strings that
would be acceptable numbers in Emacs ELisp. The second is a list of strings
that are not valid numbers. The code tests each string in each list.
<syntaxhighlight lang="lisp">
(setq valid-strings '("3" "0" "-0" "2." "1000" "-4" "-5." "6.2" "-8.45" "+15e2" "-15e2" "#b101100" "#o54" "#x2c" "1500.0" "#24r1k" "3"))
 
(setq invalid-strings '("3cat" "1,000" "5.6.7" "cat3" "def" "zero"))
 
(with-current-buffer (pop-to-buffer "my-test")
(erase-buffer)
(insert "Test for valid strings:\n")
(dolist (test-string valid-strings)
(let ((test-result))
(setq test-result (string-valid-number-p test-string))
(insert (format "%-8s - %s \n" test-string test-result))))
(insert "\n" "\n")
(insert "Test for invalid strings:\n")
(dolist (test-string invalid-strings)
(let ((test-result))
(setq test-result (string-valid-number-p test-string))
(insert (format "%-5s - %s \n" test-string test-result)))))
</syntaxhighlight>
Below is the result of the tests:
<pre>
Test for valid strings:
3 - t
0 - t
-0 - t
2. - t
1000 - t
-4 - t
-5. - t
6.2 - t
-8.45 - t
+15e2 - t
-15e2 - t
#b101100 - t
#o54 - t
#x2c - t
1500.0 - t
#24r1k - t
3 - t
 
 
Test for invalid strings:
3cat - nil
1,000 - nil
5.6.7 - nil
cat3 - nil
def - nil
zero - nil
</pre>
 
=={{header|EMal}}==
<syntaxhighlight lang="emal">
fun isNumeric = logic by text value
try
^|So funny:
|a) we check if it's castable to a real
|b) we obtain the real 0.0
|c) conversion from real to int to get 0
|d) int can be converted to logical to get ⊥
|e) we can negate the result
|^
return not when(value.contains("."), logic!int!(real!value * 0), logic!(int!value * 0))
remedy
return false
end
end
fun main = int by List args
if args.length == 1
writeLine(isNumeric(args[0]))
else
writeLine("value".padEnd(8, " ") + " " + "numeric")
for each text value in text["0o755", "thursday", "3.14", "0b1010", "-100", "0xff"]
writeLine(value.padEnd(8, " ") + " " + isNumeric(value))
end
end
return 0
end
exit main(Runtime.args)
</syntaxhighlight>
{{out}}
<pre>
value numeric
0o755 ⊤
thursday ⊥
3.14 ⊤
0b1010 ⊤
-100 ⊤
0xff ⊤
</pre>
 
Line 2,099 ⟶ 2,221:
The 'fromStr' methods return a parsed number or given an error. The 'false' tells each method to return null if the string does not parse as a number of given type, otherwise, the 'fromStr' method throws an exception.
 
<syntaxhighlight lang="fantomjava">
 
class Main
{
Line 2,133 ⟶ 2,256:
For '2a5': false
For '-2.1e5': true
</pre>
 
Another example inspired by the Kotlin example. Fantom does not have an enhanced for-loop (foreach) loop, but instead uses Closures as the primary mechanism of iteration.
 
<syntaxhighlight lang="java">
/* gary chike 08/27/2023 */
 
class Main {
static Void main() {
inputs := ["152\n", "-3.141", "Foo123", "-0", "456bar", "1.0E10"]
 
inputs.each |Str input| { echo("$input.trim \tis " + (isNumeric(input) ? "numeric" : "not numeric"))}
 
static Bool isNumeric(Str input) {
try {
input.toFloat
return true
}
catch(Err e) {
return false
}
}
}
</syntaxhighlight>
{{out}}
<pre>
152 is numeric
-3.141 is numeric
Foo123 is not numeric
-0 is numeric
456bar is not numeric
1.0E10 is numeric
</pre>
 
Line 2,189 ⟶ 2,344:
isNumeric := (integerError = 0) or (realError = 0);
end;
end;</syntaxhighlight>
</syntaxhighlight>
 
The following is a more complete and compilable example.
 
<syntaxhighlight lang="pascal">
program IsNumeric;
 
type
TDynamicArrayItem = record
StrValue: string;
end;
 
var
myDynamicArray: array of TDynamicArrayItem;
i: Integer;
Value: Extended;
Code: Integer;
 
begin
// Initialize the dynamic array with different data types
SetLength(myDynamicArray, 7);
myDynamicArray[0].StrValue := 'Hello';
myDynamicArray[1].StrValue := '42';
myDynamicArray[2].StrValue := '3.14159';
myDynamicArray[3].StrValue := 'World';
myDynamicArray[4].StrValue := '99';
myDynamicArray[5].StrValue := '0777'; // Octal representation for 511
myDynamicArray[6].StrValue := '$A1'; // Hexadecimal representation for 161
 
// Iterate through the dynamic array and determine data type
for i := Low(myDynamicArray) to High(myDynamicArray) do
begin
Val(myDynamicArray[i].StrValue, Value, Code);
if Code = 0 then // The value 0 for Code indicates that the conversion was successful.
Writeln('Element ', i, ': Numeric Value ', Chr(9),' - ', Value) // Chr(9) = tab
else
Writeln('Element ', i, ': Non-Numeric Value ', Chr(9), ' - ', myDynamicArray[i].StrValue);
end;
end.
{ Val converts the value represented in the string 'StrValue' to a numerical value or an enumerated value, and stores this value in the variable 'Value', which can be of type Longint, Real and Byte or any enumerated type. If the conversion isn't successful, then the parameter 'Code' contains the index of the character in 'StrValue' which prevented the conversion. }
 
</syntaxhighlight>
 
{{out}}:
<pre>
Free Pascal Compiler version 3.2.2 [2021/10/28] for x86_64
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Darwin for x86_64
Compiling arrVariantIsNumeric.pas
Assembling arrvariantisnumeric
Linking arrVariantIsNumeric
37 lines compiled, 0.3 sec
 
Element 0: Non-Numeric Value - Hello
Element 1: Numeric Value - 4.20000000000000000000E+0001
Element 2: Numeric Value - 3.14158999999999999993E+0000
Element 3: Non-Numeric Value - World
Element 4: Numeric Value - 9.90000000000000000000E+0001
Element 5: Numeric Value - 7.77000000000000000000E+0002
Element 6: Non-Numeric Value - $A1
</pre>
 
=={{header|FreeBASIC}}==
Line 2,554 ⟶ 2,770:
if isnumeric('picklejuice') then print, 'yes' else print, 'no'
; ==> no</syntaxhighlight>
 
=={{header|Insitux}}==
 
Non-null and non-false values are truthy in Insitux. The operation <b>to-num</b> returns null if it is unable to parse its string parameter, else the parsed number. The operation <b>bool</b> is unnecessary in most situations, but is composed with <b>to-num</b> here to satisfy the task specification.
 
<syntaxhighlight lang="insitux">> (var numeric? (comp to-num bool))
(comp to-num bool)
 
> (numeric? "123")
true
 
> (numeric? "0x25")
true
 
> (numeric? "0b0101")
true
 
> (numeric? "hello")
false
 
> (numeric? "123x456")
false</syntaxhighlight>
 
=={{header|J}}==
Line 2,573 ⟶ 2,811:
 
=={{header|Java}}==
Typically, you would use the 'parse' methods from either the ''Integer'', ''Long'', ''Float'', or ''Double'' class, <br />which will throw a ''NumberFormatException'' for ill-formed values.<br />
For example
<syntaxhighlight lang="java">
Integer.parseInt("12345")
</syntaxhighlight>
<syntaxhighlight lang="java">
Float.parseFloat("123.456")
</syntaxhighlight>
The performance mark is somewhat negligible between a try-block and custom methods.
<syntaxhighlight lang="java">
public static void main(String[] args) {
String value;
value = "1234567";
System.out.printf("%-10s %b%n", value, isInteger(value));
value = "12345abc";
System.out.printf("%-10s %b%n", value, isInteger(value));
value = "-123.456";
System.out.printf("%-10s %b%n", value, isFloatingPoint(value));
value = "-.456";
System.out.printf("%-10s %b%n", value, isFloatingPoint(value));
value = "123.";
System.out.printf("%-10s %b%n", value, isFloatingPoint(value));
value = "123.abc";
System.out.printf("%-10s %b%n", value, isFloatingPoint(value));
}
 
static boolean isInteger(String string) {
String digits = "0123456789";
for (char character : string.toCharArray()) {
if (!digits.contains(String.valueOf(character)))
return false;
}
return true;
}
 
static boolean isFloatingPoint(String string) {
/* at least one decimal-point */
int indexOf = string.indexOf('.');
if (indexOf == -1)
return false;
/* assure only 1 decimal-point */
if (indexOf != string.lastIndexOf('.'))
return false;
if (string.charAt(0) == '-' || string.charAt(0) == '+') {
string = string.substring(1);
indexOf--;
}
String integer = string.substring(0, indexOf);
if (!integer.isEmpty()) {
if (!isInteger(integer))
return false;
}
String decimal = string.substring(indexOf + 1);
if (!decimal.isEmpty())
return isInteger(decimal);
return true;
}
</syntaxhighlight>
<pre>
1234567 true
12345abc false
-123.456 true
-.456 true
123. true
123.abc false
</pre>
<br />
It's generally bad practice in Java to rely on an exception being thrown since exception handling is relatively expensive. If non-numeric strings are common, you're going to see a huge performance hit.
<syntaxhighlight lang="java">public boolean isNumeric(String input) {
Line 2,635 ⟶ 2,940:
 
=={{header|jq}}==
'''Works with jq, the C implementation of jq'''
In versions of jq that support try/catch, the simplest way to test if a string can be parsed as a number is:<syntaxhighlight lang="jq">try tonumber catch false</syntaxhighlight>
 
'''Works with gojq, the Go implementation of jq'''
 
'''Works with jaq, the Rust implementation of jq'''
 
The simplest way to test if a string can be parsed as a number is:<syntaxhighlight lang="jq">try tonumber catch false</syntaxhighlight>
The above expression will emit the corresponding number, or false if there is none. Here then is a boolean filter which will also emit true for each input that is a number:
<syntaxhighlight lang="jq">def is_numeric: true and try tonumber catch false;</syntaxhighlight>
Line 3,334 ⟶ 3,645:
Inf is numeric
rose is not numeric</pre>
 
=={{header|Nu}}==
<syntaxhighlight lang="nu">
def is-numeric [] {try {into float | true} catch {false}}
 
["1" "12" "-3" "5.6" "-3.14" "one" "cheese"] | each {{k: $in, v: ($in | is-numeric)}}
</syntaxhighlight>
{{out}}
<pre>
╭───┬────────┬───────╮
│ # │ k │ v │
├───┼────────┼───────┤
│ 0 │ 1 │ true │
│ 1 │ 12 │ true │
│ 2 │ -3 │ true │
│ 3 │ 5.6 │ true │
│ 4 │ -3.14 │ true │
│ 5 │ one │ false │
│ 6 │ cheese │ false │
╰───┴────────┴───────╯
</pre>
 
=={{header|Objeck}}==
Line 3,485 ⟶ 3,817:
=={{header|Pascal}}==
See [[#Delphi|Delphi]] or [[#Free Pascal|Free Pascal]].
 
 
=={{header|PascalABC.NET}}==
<syntaxhighlight lang="pascal">
function IsNumeric(s: string): boolean;
begin
var i: integer;
Result := integer.TryParse(s,i)
end;
 
begin
var s := '123';
if IsNumeric(s) then
Print('string is numeric')
end.
</syntaxhighlight>
 
=={{header|PeopleCode}}==
Line 4,172 ⟶ 4,520:
isdigit("0123a") # print 0
</syntaxhighlight>
 
=={{header|RPL}}==
This one-liner returns 1 if the string is either a real number, a complex number or a binary integer - and zero otherwise.
≪ '''IFERR''' STR→ '''THEN''' DROP 0 '''ELSE''' TYPE { 0 1 10 } SWAP POS SIGN '''END''' ≫ ‘<span style="color:blue">NUM?</span>’ STO
 
=={{header|Ruby}}==
Line 4,245 ⟶ 4,597:
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">// This function is not limited to just numeric types but rather anything that implements the FromStr trait.
// This function is not limited to just numeric types but rather anything that implements the FromStr trait.
fn parsable<T: FromStr>(s: &str) -> bool {
s.parse::<T>().is_ok()
}
}</syntaxhighlight>
</syntaxhighlight>
 
Sample code:
 
<syntaxhighlight lang="rust">
use std::str::FromStr;
 
fn parsable<T: FromStr>(s: &str) -> bool {
s.parse::<T>().is_ok()
}
 
fn main() {
let test_cases = [
"142857",
"3.14",
"not of this earth!"
];
 
let types: &[(&str, fn(&str) -> bool)] = &[
("i32", parsable::<i32> as fn(&str) -> bool),
("i64", parsable::<i32> as fn(&str) -> bool),
("i128", parsable::<i32> as fn(&str) -> bool),
("f64", parsable::<f64> as fn(&str) -> bool),
];
 
println!("");
for &case in &test_cases {
for &(type_name, parse_fn) in types {
println!(
"'{}' {} be parsed as {}",
case,
if parse_fn(case) { "can" } else { "_cannot_" },
type_name
);
}
println!("");
}
}
</syntaxhighlight>
 
{{out}}
<pre>
'142857' can be parsed as i32
'142857' can be parsed as i64
'142857' can be parsed as i128
'142857' can be parsed as f64
 
'3.14' _cannot_ be parsed as i32
'3.14' _cannot_ be parsed as i64
'3.14' _cannot_ be parsed as i128
'3.14' can be parsed as f64
 
'not of this earth!' _cannot_ be parsed as i32
'not of this earth!' _cannot_ be parsed as i64
'not of this earth!' _cannot_ be parsed as i128
'not of this earth!' _cannot_ be parsed as f64
</pre>
 
=={{header|Scala}}==
Line 4,915 ⟶ 5,326:
{{libheader|Wren-fmt}}
Wren's Num class already has a static method which does what this task requires.
<syntaxhighlight lang="ecmascriptwren">import "./fmt" for Fmt
 
System.print("Are these strings numeric?")
Line 4,940 ⟶ 5,351:
<syntaxhighlight lang="xlisp">(DEFUN NUMERICP (X)
(IF (STRING->NUMBER X) T))</syntaxhighlight>
 
=={{header|XPL0}}==
The compiler is more strict in the characters it accepts as numeric than
what is accepted here. This program indicates more of what the input
intrinsics (IntIn, RlIn and HexIn) would accept as numeric.
<syntaxhighlight lang "XPL0">string 0;
 
func IsNumeric(Str);
char Str;
[while Str(0) # 0 do
[if Str(0) >= ^0 and Str(0) <= ^9 then return true;
if Str(0) = ^$ then
[if Str(1) >= ^0 and Str(1) <= ^9 then return true;
if Str(1) >= ^A and Str(1) <= ^F then return true;
if Str(1) >= ^a and Str(1) <= ^f then return true;
];
Str:= Str+1;
];
return false;
];
 
int Strs, S;
[Text(0, "Are these strings numeric?^m^j");
Strs:= ["1", "3.14", "-100", "1e2", "NaN", "$af", "%1_1011", "rose", ". 3", "num9", "x$ 9", "x$ a"];
for S:= 0 to 12-1 do
[Text(0, if IsNumeric(Strs(S)) then "yes : " else "no : ");
Text(0, Strs(S));
CrLf(0);
];
]</syntaxhighlight>
{{out}}
<pre>
Are these strings numeric?
yes : 1
yes : 3.14
yes : -100
yes : 1e2
no : NaN
yes : $af
yes : %1_1011
no : rose
yes : . 3
yes : num9
yes : x$ 9
no : x$ a
</pre>
 
=={{header|Z80 Assembly}}==
Line 5,157 ⟶ 5,614:
 
</pre>
 
=={{header|Zig}}==
<syntaxhighlight lang="zig">
const std = @import("std");
const stdout = std.io.getStdOut().writer();
 
fn isNumeric(str: []const u8) bool {
const num = std.mem.trim(u8, str, "\x20");
_ = std.fmt.parseFloat(f64, num) catch return false;
return true;
}
 
pub fn main() !void {
const s1 = " 123";
const s2 = " +123";
const s3 = " 12.3";
const s4 = "-12.3";
const s5 = "12e-3";
const s6 = "=12-3";
const s7 = "abcde";
const s8 = "12cde";
const s9 = "NaN";
const s10 = "0xFF";
 
try stdout.print("Is {s} numeric? {}\n", .{ s1, isNumeric(s1) });
try stdout.print("Is {s} numeric? {}\n", .{ s2, isNumeric(s2) });
try stdout.print("Is {s} numeric? {}\n", .{ s3, isNumeric(s3) });
try stdout.print("Is {s} numeric? {}\n", .{ s4, isNumeric(s4) });
try stdout.print("Is {s} numeric? {}\n", .{ s5, isNumeric(s5) });
try stdout.print("Is {s} numeric? {}\n", .{ s6, isNumeric(s6) });
try stdout.print("Is {s} numeric? {}\n", .{ s7, isNumeric(s7) });
try stdout.print("Is {s} numeric? {}\n", .{ s8, isNumeric(s8) });
try stdout.print("Is {s} numeric? {}\n", .{ s9, isNumeric(s9) });
try stdout.print("Is {s} numeric? {}\n", .{ s10, isNumeric(s10) });
}
</syntaxhighlight>
 
{{out}}
<pre>
Is 123 numeric? true
Is +123 numeric? true
Is 12.3 numeric? true
Is -12.3 numeric? true
Is 12e-3 numeric? true
Is =12-3 numeric? false
Is abcde numeric? false
Is 12cde numeric? false
Is NaN numeric? true
Is 0xFF numeric? true
</pre>
 
 
 
=={{header|zkl}}==
104

edits