Determine if a string is numeric: Difference between revisions

added C translation to C++
m (syntax highlighting fixup automation)
(added C translation to C++)
 
(21 intermediate revisions by 15 users not shown)
Line 1,469:
'192.168.0.1' Not numeric
</pre>
 
=={{header|BQN}}==
<syntaxhighlight lang="bqn">IsNumeric ← 1∘•ParseFloat⎊0</syntaxhighlight>
 
=={{header|Bracmat}}==
Line 1,484 ⟶ 1,487:
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,518:
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,531:
 
<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,574:
 
=={{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,975:
 
=={{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,047 ⟶ 2,017:
<pre>
["123", "-12.3", "-12e5", "+123"]
</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,109:
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,144:
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,232:
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,306 ⟶ 2,410:
123xyz (base 10) => false
xyz (base 10) => false
</pre>
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">include "NSLog.incl"
 
local fn StringIsNumeric( string as CFStringRef ) as BOOL
BOOL flag = NO
ScannerRef scanner = fn ScannerWithString( string )
if ( fn ScannerScanFloat( scanner, NULL ) )
flag = fn ScannerIsAtEnd( scanner )
end if
end fn = flag
 
NSLog(@"%d",fn StringIsNumeric( @"1.23" ))
NSLog(@"%d",fn StringIsNumeric( @"-123.4e5" ))
NSLog(@"%d",fn StringIsNumeric( @"alpha" ))
 
HandleEvents</syntaxhighlight>
 
{{out}}
<pre>
1
1
0
</pre>
 
Line 2,530 ⟶ 2,658:
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,549 ⟶ 2,699:
 
=={{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 3,310 ⟶ 3,527:
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,419 ⟶ 3,657:
disp(isnum("123bar")) % 0
disp(isnum("3.1415")) % 1</syntaxhighlight>
 
=={{header|Odin}}==
 
<syntaxhighlight lang="odin">package main
 
import "core:strconv"
import "core:fmt"
 
is_numeric :: proc(s: string) -> bool {
_, ok := strconv.parse_f32(s)
return ok
}
 
main :: proc() {
strings := []string{"1", "3.14", "-100", "1e2", "Inf", "rose"}
for s in strings {
fmt.println(s, "is", is_numeric(s) ? "numeric" : "not numeric")
}
}
 
/* Output:
1 is numeric
3.14 is numeric
-100 is numeric
1e2 is numeric
Inf is not numeric
rose is not numeric
*/</syntaxhighlight>
 
=={{header|Oz}}==
Line 4,120 ⟶ 4,386:
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,829 ⟶ 5,099:
End If</syntaxhighlight>
 
=={{header|V (Vlang)}}==
<syntaxhighlight lang="v (vlang)">import strconv
 
fn is_numeric(s string) bool {
Line 4,863 ⟶ 5,133:
{{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,888 ⟶ 5,158:
<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}}==
{{works with|CP/M 3.1|YAZE-AG-2.51.2 Z80 emulator}}
{{works with|ZSM4 macro assembler|YAZE-AG-2.51.2 Z80 emulator}}
Use the /S8 switch on the ZSM4 assembler for 8 significant characters for labels and names
<syntaxhighlight lang="z80">
;
; Check if input string is a number using Z80 assembly language
;
; Runs under CP/M 3.1 on YAZE-AG-2.51.2 Z80 emulator
; Assembled with zsm4 on same emulator/OS, uses macro capabilities of said assembler
; Created with vim under Windows
;
; 2023-04-04 Xorph
;
 
;
; Useful definitions
;
 
bdos equ 05h ; Call to CP/M BDOS function
strdel equ 6eh ; Set string delimiter
readstr equ 0ah ; Read string from console
wrtstr equ 09h ; Write string to console
 
nul equ 00h ; ASCII control characters
esc equ 1bh
cr equ 0dh
lf equ 0ah
 
cnull equ '0' ; ASCII character constants
cnine equ '9'
cminus equ '-'
cdot equ '.'
 
buflen equ 30h ; Length of input buffer
minbit equ 00h ; Bit 0 is used as flag for '-'
dotbit equ 01h ; Bit 1 is used as flag for '.'
 
;
; Macros for BDOS calls
;
 
setdel macro char ; Set string delimiter to char
ld c,strdel
ld e,char
call bdos
endm
 
print macro msg ; Output string to console
ld c,wrtstr
ld de,msg
call bdos
endm
 
newline macro ; Print newline
ld c,wrtstr
ld de,crlf
call bdos
endm
 
readln macro buf ; Read a line from input
ld c,readstr
ld de,buf
call bdos
endm
 
;
; =====================
; Start of main program
; =====================
;
 
cseg
 
isnum:
setdel nul ; Set string terminator to nul ('\0') - '$' is default in CP/M
print help
newline
newline
 
readnum:
ld b,buflen ; Clear input buffer
ld hl,bufcont
clrloop:
ld (hl),0
inc hl
djnz clrloop
 
readln inputbuf ; Read a line from input
newline ; Newline is discarded during input, so write one...
 
ld a,(inputbuf+1) ; Length of actual input
cp 0 ; If empty input, quit
ret z
 
ld b,a ; Loop counter for djnz instruction
ld c,0 ; Use c for flags: '-' and '.' may be encountered at most once, '-' only at start
ld hl,bufcont ; Start of actual input
 
loop:
ld a,(hl) ; Get next character into a
 
cp cminus ; Check minus sign
jr z,chkminus
 
cp cdot ; Check dot
jr z,chkdot
 
cp cnull ; Check if below '0'
jr c,notanum
 
cp cnine+1 ; Check if above '9'
jr nc,notanum
 
checknxt:
set minbit,c ; Whatever the case, no more '-' are allowed after the first character
inc hl ; Increase hl to next character and repeat until done
djnz loop
 
print bufcont ; If we made it this far, we are done and the string is numeric
print yesmsg
newline
newline
 
done:
jp readnum ; Read next input from user until terminated with ^C or empty input
ret ; Return to CP/M (unreachable code)
 
notanum:
print bufcont ; Print failure message
print nomsg
newline
newline
jr done
 
chkminus:
bit minbit,c ; If a '-' is encountered and the flag is already set, the string is not numeric
jr nz,notanum
set minbit,c ; Otherwise, set flag and check next character
jr checknxt
 
chkdot:
bit dotbit,c ; If a '.' is encountered and the flag is already set, the string is not numeric
jr nz,notanum
set dotbit,c ; Otherwise, set flag and check next character
jr checknxt
 
;
; ===================
; End of main program
; ===================
;
 
;
; ================
; Data definitions
; ================
;
 
dseg
 
help:
defz 'Enter numbers to check, end with empty line or ^C'
 
inputbuf: ; Input buffer for CP/M BDOS call
defb buflen ; Maximum possible length
defb 00h ; Returned length of actual input
bufcont:
defs buflen ; Actual input area
defb nul ; Null terminator for output, if buffer is filled completely
 
yesmsg:
defz ' is numeric'
nomsg:
defz ' is not numeric'
 
crlf: defb cr,lf,nul ; Generic newline
 
</syntaxhighlight>
 
{{out}}
<pre>
E>isnum
Enter numbers to check, end with empty line or ^C
 
1234
1234 is numeric
 
hello
hello is not numeric
 
12.34
12.34 is numeric
 
-98.76
-98.76 is numeric
 
4.6.76
4.6.76 is not numeric
 
34-56-23
34-56-23 is not numeric
 
-.9876543210
-.9876543210 is numeric
 
444555.
444555. is numeric
 
1234c
1234c is not numeric
 
123e45
123e45 is not numeric
 
</pre>
 
=={{header|zkl}}==
3

edits