Getting the number of decimal places: Difference between revisions
Added various BASIC dialects (True BASIC256 and Run BASIC)
(Added various BASIC dialects (True BASIC256 and Run BASIC)) |
|||
(30 intermediate revisions by 18 users not shown) | |||
Line 1:
{{draft task}}
;Task:
Write a program (function) to get the number of
Line 11:
(Note that the reference implementation – in the '''Ring''' language – shows a function over a given '''number''' rather than a given numeric string, and that the sample values shown above are not enclosed in quotes).
<br><br>
=={{header|11l}}==
{{trans|Python}}
<syntaxhighlight lang="11l">F dec(n)
R I ‘.’ C n {n.split(‘.’).last.len} E 0
print(dec(‘12.345’))
print(dec(‘12.3450’))</syntaxhighlight>
{{out}}
<pre>
3
4
</pre>
=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
<syntaxhighlight lang="action!">INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit
BYTE FUNC FindC(CHAR ARRAY s CHAR c)
BYTE i
FOR i=1 TO s(0)
DO
IF s(i)=c THEN
RETURN (i)
FI
OD
RETURN (0)
BYTE FUNC DecimalCount(REAL POINTER r)
CHAR ARRAY s(20),sub(20)
BYTE i,dotPos,ePos,count
INT exp
StrR(r,s)
ePos=FindC(s,'E)
IF ePos>0 THEN
ePos==+1
IF s(ePos)='+ THEN
ePos==+1
FI
SCopyS(sub,s,ePos,s(0))
exp=ValI(sub)
ELSE
exp=0
FI
dotPos=FindC(s,'.)
count=0
IF dotPos>0 THEN
FOR i=dotPos+1 TO s(0)
DO
IF s(i)<'0 OR s(i)>'9 THEN
EXIT
FI
count==+1
OD
FI
IF exp<0 THEN
count==-exp
ELSEIF exp<count THEN
count==-exp
ELSE
count=0
FI
RETURN (count)
PROC Test(REAL POINTER r)
BYTE count
count=DecimalCount(r)
PrintR(r)
PrintF(" has %I decimals%E",count)
RETURN
PROC Main()
REAL r
Put(125) PutE() ;clear screen
ValR("1234",r) Test(r)
ValR("123.4",r) Test(r)
ValR("12.34",r) Test(r)
ValR("1.234",r) Test(r)
ValR("0.1234",r) Test(r)
ValR("1.234E-3",r) Test(r)
ValR("1.234E-10",r) Test(r)
ValR("1.E-10",r) Test(r)
ValR("1.23456789E10",r) Test(r)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Getting_the_number_of_decimals.png Screenshot from Atari 8-bit computer]
<pre>
1234 has 0 decimals
123.4 has 1 decimals
12.34 has 2 decimals
1.234 has 3 decimals
.1234 has 4 decimals
1.234E-03 has 6 decimals
1.234E-10 has 13 decimals
1E-10 has 10 decimals
1.23456789E+10 has 0 decimals
</pre>
=={{header|Ada}}==
<syntaxhighlight lang="ada">
-- Report the number of decimal places in a number
-- J. Carter 2023 Apr
-- I presume the input is a String containing the image of the value; the test values of 12.345 & 12.3450 represent the same number,
-- and so would give the same result otherwise
with Ada.Strings.Fixed;
with Ada.Text_IO;
procedure Decimal_Places is
function Num_Places (Number : in String) return Natural;
-- Returns the number of decimal places in the numeric image in Number
function Num_Places (Number : in String) return Natural is
Dot : constant Natural := Ada.Strings.Fixed.Index (Number, ".");
begin -- Num_Places
if Dot = 0 then
return 0;
end if;
return Number'Last - Dot;
end Num_Places;
Test_1 : constant String := "12.345";
Test_2 : constant String := "12.3450";
begin -- Decimal_Places
Ada.Text_IO.Put_Line (Item => Test_1 & (1 .. 10 - Test_1'Length => ' ') & Num_Places (Test_1)'Image);
Ada.Text_IO.Put_Line (Item => Test_2 & (1 .. 10 - Test_2'Length => ' ') & Num_Places (Test_2)'Image);
end Decimal_Places;
</syntaxhighlight>
{{out}}
<pre>
12.345 3
12.3450 4
</pre>
=={{header|Arturo}}==
<syntaxhighlight lang="arturo">nofDecimals: function [n][
str: (string? n)? -> n -> to :string n
size last split.by:"." str
]
loop [12 12.345 "12.3450" 12.34567] 'n ->
print ["number of decimals of" n "->" nofDecimals n]</syntaxhighlight>
{{out}}
<pre>number of decimals of 12 -> 2
number of decimals of 12.345 -> 3
number of decimals of 12.3450 -> 4
number of decimals of 12.34567 -> 5</pre>
=={{header|AutoHotkey}}==
<
output .= v " has " StrLen(StrSplit(v, ".").2) " decimals.`n"
MsgBox % output</
{{out}}
<pre>10 has 0 decimals.
Line 23 ⟶ 182:
12.3450 has 4 decimals.
12.3450 has 4 decimals.</pre>
=={{header|AWK}}==
<syntaxhighlight lang="awk">
# syntax: GAWK -f GETTING_THE_NUMBER_OF_DECIMALS.AWK
BEGIN {
Line 35 ⟶ 195:
exit(0)
}
</syntaxhighlight>
{{out}}
<pre>
Line 45 ⟶ 205:
</pre>
=={{header|
==={{header|BASIC256}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="vbnet">arraybase 1
dim n[5]
n[1] = 7
n[2] = 12.00
n[3] = 12.345
n[4] = 12.345677
n[5] = 0.142857142857142
for i = n[?,] to n[?]
print n[i] + " has " + dec(n[i]) + " decimals"
next i
end
function dec(n)
c = string(n)
if instr(c, ".") then return length(mid(c, instr(c, ".") + 1, length(c))) else return 0
end function</syntaxhighlight>
{{out}}
<pre>7 has 0 decimals
12.0 has 1 decimals
12.345 has 3 decimals
12.345677 has 6 decimals
0.14285714286 has 11 decimals</pre>
==={{header|Chipmunk Basic}}===
{{trans|Yabasic}}
{{works with|Chipmunk Basic|3.6.4}}
<syntaxhighlight lang="vbnet">100 dim n(4)
110 data 7,12,12.345,12.345677,0.142857
120 for i = 0 to 4
130 read n(i)
140 print n(i);" has ";dek(n(i));" decimals"
150 next i
160 end
170 sub dek(n)
180 c$ = str$(n)
190 if instr(c$,".") then dek = len(mid$(c$,instr(c$,".")+1)) else dek = 0
200 end sub</syntaxhighlight>
==={{header|FreeBASIC}}===
<syntaxhighlight lang="vbnet">Function dec(n As Double) As Uinteger
Dim As String c = Str(n)
Return Iif(Instr(c, "."), Len(Mid(c,Instr(c, ".")+1)), 0)
End Function
Dim As Double n(1 To ...) => {7, 12.00, 12.345, 12.345677, 0.142857142857142}
For i As Integer = 1 To Ubound(n)
Print n(i); " has "; dec(n(i)); " decimals"
Next i
Sleep</syntaxhighlight>
{{out}}
<pre> 7 has 0 decimals
12 has 0 decimals
12.345 has 3 decimals
12.345677 has 6 decimals
0.142857142857142 has 15 decimals</pre>
==={{header|GW-BASIC}}===
The [[#MSX Basic|MSX Basic]] solution works without any changes.
==={{header|MSX Basic}}===
{{works with|MSX BASIC|any}}
{{works with|Chipmunk Basic}}
{{works with|GW-BASIC}}
{{works with|QBasic}}
{{works with|QB64}}
<syntaxhighlight lang="qbasic">100 DIM N(4)
110 DATA 7,12,12.345,12.345677,0.142857
120 FOR I = 0 TO 4
130 READ N(I)
140 GOSUB 180
150 PRINT N(I);"has";DEC;"decimals"
160 NEXT I
170 END
180 'sub dec(n)
190 C$ = STR$(N(I))
200 IF INSTR(C$,".") <> 0 THEN DEC = LEN(MID$(C$,INSTR(C$,".")+1)) ELSE DEC = 0
210 RETURN</syntaxhighlight>
{{out}}
<pre> 7 has 0 decimals
12 has 0 decimals
12.345 has 3 decimals
12.34568 has 5 decimals
.142857 has 6 decimals</pre>
==={{header|QBasic}}===
{{works with|QBasic|1.1}}
{{works with|QuickBasic|4.5}}
<syntaxhighlight lang="qbasic">DECLARE FUNCTION dec! (n!)
DIM n(4)
DATA 7,12.00,12.345,12.345677,0.142857142857142
FOR i = LBOUND(n) TO UBOUND(n)
READ n(i)
PRINT n(i); "has"; dec(n(i)); "decimals"
NEXT i
END
FUNCTION dec (n)
c$ = STR$(n)
IF INSTR(c$, ".") THEN dec = LEN(MID$(c$, INSTR(c$, ".") + 1)) ELSE dec = 0
END FUNCTION</syntaxhighlight>
==={{header|QB64}}===
{{works with|QBasic}}
<syntaxhighlight lang="vbnet">Dim n(4)
Data 7,12.00,12.345,12.345677,0.142857142857142
For i = LBound(n) To UBound(n)
Read n(i)
Print n(i); "has"; dec(n(i)); "decimals"
Next i
End
Function dec (n)
c$ = Str$(n)
If InStr(c$, ".") Then dec = Len(Mid$(c$, InStr(c$, ".") + 1)) Else dec = 0
End Function</syntaxhighlight>
==={{header|Run BASIC}}===
{{trans|Yabasic}}
{{works with|Just BASIC}}
{{works with|Liberty BASIC}}
<syntaxhighlight lang="vb">dim n(4)
n(0) = 7
n(1) = 12.00
n(2) = 12.345
n(3) = 12.345677
n(4) = 0.142857142857142
for i = 0 to 4
print n(i); " has "; dek(n(i)); " decimals"
next i
end
function dek(n)
c$ = str$(n)
if instr(c$, ".") then dek = len(mid$(c$, instr(c$, ".") + 1)) else dek = 0
end function</syntaxhighlight>
==={{header|True BASIC}}===
{{trans|QBasic}}
<syntaxhighlight lang="qbasic">FUNCTION dec(n_t)
LET c$ = STR$(n_t)
IF POS(c$,".")<>0 THEN LET dec = LEN((c$)[POS(c$,".")+1:maxnum]) ELSE LET dec = 0
END FUNCTION
DIM n(5)
DATA 7, 12.00, 12.345, 12.345677, 0.142857142857142
FOR i = LBOUND(n) TO UBOUND(n)
READ n(i)
PRINT n(i); "has"; dec(n(i)); "decimals"
NEXT i
END</syntaxhighlight>
{{out}}
<pre>Same as QBasic entry.</pre>
==={{header|Yabasic}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="vb">dim n(4)
data 7,12.00,12.345,12.345677,0.142857142857142
for i = 0 to 4
read n(i)
print n(i), " has ", dek(n(i)), " decimals"
next i
end
sub dek(n)
c$ = str$(n)
if instr(c$, ".") then return len(mid$(c$, instr(c$, ".") + 1)) else return 0: fi
end sub</syntaxhighlight>
{{out}}
<pre>7 has 0 decimals
12 has 0 decimals
12.345 has 3 decimals
12.3457 has 4 decimals
0.142857 has 6 decimals</pre>
=={{header|C}}==
<syntaxhighlight lang="c">#include <stdio.h>
#include <string.h>
int findNumOfDec(const char *s) {
int pos = 0;
while (s[pos] && s[pos++] != '.') {}
return strlen(s + pos);
}
void test(
int num = findNumOfDec(
printf("%s has %d decimal%s\n", s, num, p);
}
int main() {
test("12
test("12.
test("12.
test("12.
test("12.
test(
char str[64];
sprintf(str, "%f", 1.2345e+54);
test(str);
return 0;
}</
{{out}}
<pre>
12
12.
12.
12.
12.3450 has 4 decimals
12.34555555555555555555 has 20 decimals
1234500000000000060751116919315055127939946206157864960.000000 has 6 decimals
</pre>
=={{header|C++}}==
{{trans|C}}
<
#include <
int findNumOfDec(const char *s) {
int pos = 0;
return strlen(s + pos);
}
void test(
const char *p = num != 1 ? "s" : "";
std::cout << s << " has " << num << " decimal" << p << "\n";
}
int main() {
test("12
test("12.
test("12.
test("12.
test("12.
test(
char str[64];
sprintf(str, "%f", 1.2345e+54);
test(str);
return 0;
}</
{{out}}
<pre>
12 has 0 decimals
12.0 has 1 decimal
12.345 has 3 decimals
12.
12.
12.
1234500000000000060751116919315055127939946206157864960.000000 has 6 decimals
</pre>
=={{header|EasyLang}}==
<syntaxhighlight>
func ndec n .
while abs (n - floor (n + 1e-15)) > 1e-15
n *= 10
r += 1
.
return r
.
for i in [ 0.00000000000001 12.345 12.3450 1.1 0.1234567 ]
write ndec i & " "
.
</syntaxhighlight>
{{out}}
<pre>
14 3 3 1 7
</pre>
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
//Getting the number of decimal places. Nigel Galloway: March 23rd., 2023.
let fN g=let n,g=Seq.length g,g|>Seq.tryFindIndex((=)'.') in match g with Some g->n-g-1 |_->0
["12";"12.00";"12.345";"12.3450";"12.34500"]|>List.iter(fN>>printfn "%d")
</syntaxhighlight>
{{out}}
<pre>
0
2
3
4
5
</pre>
=={{header|Go}}==
{{trans|Wren}}
<
import (
Line 203 ⟶ 559:
}
}
}</
{{out}}
Line 214 ⟶ 570:
1.2345e+54 has 0 decimals
</pre>
=={{Header|Haskell}}==
<syntaxhighlight lang="haskell">decimal :: String -> Int
decimal [] = 0
decimal ('.':xs) = length xs
decimal (_:xs) = decimal xs
numDecimal :: Double -> Int
numDecimal = decimal . show
main = print . map numDecimal $ [12.0, 12.345, 12.3450, 12.345555555555, 12.34555555555555555555, 1.2345e+54]</syntaxhighlight>
{{out}}
<pre>[1,3,3,12,15,7]</pre>
=={{header|Java}}==
<syntaxhighlight lang="java">
int decimalPlaces(double value) {
String string = String.valueOf(value);
return string.length() - (string.indexOf('.') + 1);
}
</syntaxhighlight>
Or
<syntaxhighlight lang="java">public static int findNumOfDec(double x){
String str = String.valueOf(x);
if(str.endsWith(".0")) return 0;
else return (str.substring(str.indexOf('.')).length() - 1);
}</
=={{header|jq}}==
The current (March 2023) official releases of jq, gojq, fq, and jaq cannot be relied upon
to preserve the literal form of numbers, and in particular they drop the
final 0 of `12.3450` when presented as a number. However, the current "master" version of jq retains
the literal form of numbers. Accordingly, both the numeric and the string forms of 12.3450 are included in the suite of test
cases, and two sets of results are presented below.
<syntaxhighlight lang=jq>
def number_decimal_digits:
. as $in
| def nil: . == null or . == "";
def nodecimal: # e.g. 12 or 12e-2
capture("^[-+]?[0-9]*([eE](?<sign>[-+]?)(?<p>[0-9]+))?$")
| if .sign|nil then 0
elif .p|nil then "internal error: \($in)"|error
else .p|tonumber
end;
tostring
| nodecimal
// capture("^[-+]?[0-9]*[.](?<d>[0-9]+)([eE](?<sign>[-+]?)(?<p>[0-9]+))?$") # has decimal
// null
| if type == "number" then .
elif not then 0
elif .d|nil then 0
elif (.sign|nil) and .p == null then .d|length
elif (.sign|nil) or .sign == "+" then [0, (.d|length) - (.p|tonumber)] | max
elif .sign == "-" then (.d|length) + (.p|tonumber)
else "internal error: \($in)"|error
end ;
def examples:
[12.345, 3],
[12.3450, 4],
["12.3450", 4],
[1e-2, 2],
[1.23e2, 0];
def task:
examples
| (first|number_decimal_digits) as $d
| if $d == last then empty
else "\(first) has \(last) decimal places but the computed value is \($d)"
end;
task, "Bye."
</syntaxhighlight>
{{output}}
Using gojq:
<pre>
12.345 has 4 decimal places but the computed value is 3
Bye.
</pre>
Using jq post-1.6:
<pre>
Bye.
</pre>
=={{header|Julia}}==
<
s = lowercase(str)
if 'e' in s
Line 244 ⟶ 675:
println("$n has $(postprecision(n)) decimals.")
end
</
<pre>
0.00100 has 5 decimals.
Line 263 ⟶ 694:
=={{header|Kotlin}}==
{{trans|Java}}
<
val str = x.toString()
if (str.endsWith(".0")) {
Line 275 ⟶ 706:
println("%f has %d decimals".format(n, findNumOfDec(n)))
}
}</
{{out}}
<pre>12.000000 has 0 decimals
Line 283 ⟶ 714:
12.345556 has 15 decimals
1234500000000000000000000000000000000000000000000000000.000000 has 7 decimals</pre>
=={{header|Lambdatalk}}==
In lambdatalk numbers are words/strings, some operators, like "+,-,*,/,...", know what to do with words like "123".
A first answer could be
<syntaxhighlight lang="scheme">
{W.length
{S.rest
{S.replace \. by space in 12.3450}}}
-> 4
</syntaxhighlight>
This is a better one, if considering that ending zeroes should not be considered as decimals
<syntaxhighlight lang="schema">
{def decimals
{def decimals.r
{lambda {:w}
{if {= {W.first :w} 0}
then {decimals.r {W.rest :w}}
else :w}}}
{lambda {:w}
{W.length
{decimals.r
{S.first
{W.reverse
{S.replace \. by space in :w}}}}}}}
-> decimals
{decimals 12.34560001230000}
-> 10
</syntaxhighlight>
Numbers can be of any size.
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[DecimalDigits]
DecimalDigits[r_String] := Module[{pos},
If[StringContainsQ[r, "."],
pos = StringPosition[r, "."][[-1, 1]];
StringLength[StringDrop[r, pos]]
,
0
]
]
DecimalDigits["12.345"]
DecimalDigits["12.3450"]
DecimalDigits["8"]
DecimalDigits["3128"]
DecimalDigits["13."]
DecimalDigits["13.1312312"]</syntaxhighlight>
{{out}}
<pre>3
4
0
0
0
7</pre>
=={{header|Perl}}==
Need pragma <code>bignum</code> to handle decimals beyond 15 digits.
<
printf "Fractional precision: %2s Number: %s\n", length((split /\./, $_)[1]) // 0, $_
for 9, 12.345, <12.3450>, 0.1234567890987654321, 1/3, 1.5**63;</
{{out}}
<pre>Fractional precision: 0 Number: 9
Line 299 ⟶ 788:
=={{header|Phix}}==
<!--(phixonline)-->
<syntaxhighlight lang="phix">
constant fracfmt = iff(machine_bits()=32?"%.14g":"%.18g")
function num_decimals(object o)
integer nd = -1
Line 327 ⟶ 818:
end if
integer dot = find('.',t)
nd = iff(dot?max(length(t)-dot-e,0):max(-e,0))
end if
s = shorten(s,
return {s,nd}
end function
Line 337 ⟶ 828:
"12.345e53", "1.2345e-08", "0.1234567890987654321",
"124093581919.648947697827373650380188008224280338254175148904323577880859375"}
for i=1 to length(tests) do
printf(1,"%25s has %d decimals\n",num_decimals(tests[i]))
end for
</syntaxhighlight>
{{out}}
32 bit
Line 367 ⟶ 859:
=={{header|Python}}==
Treated as a function over a string representation of a number to allow the capturing of significant trailing zeros.
<
...: return len(n.rsplit('.')[-1]) if '.' in n else 0
Line 376 ⟶ 868:
Out[8]: 4
In [9]: </
Or, defining a slightly less partial function, over a given number, rather than a string:
<
import math
Line 489 ⟶ 981:
# MAIN ---
if __name__ == '__main__':
main()</
{{Out}}
<pre>Decimal counts in stringifications of real and imaginary components:
Line 514 ⟶ 1,006:
want to retain them, you need to pass the value as a string. (As below.)
<syntaxhighlight lang="raku"
printf "Fractional precision: %-2s || Number: %s\n", (.split('.')[1] // '').chars, $_
for 9, 12.345, '12.3450', 0.1234567890987654321, (1.5**63).precise;
</syntaxhighlight>
{{out}}
<pre>Fractional precision: 0 || Number: 9
Line 535 ⟶ 1,027:
Any number specified in exponential notation is first converted to a whole or fractional integer (or an integer with scale), <br>and that number is then examined.
<
numeric digits 1000 /*ensure enuf dec digs for calculations*/
@.=; /*initialize a stemmed array to nulls. */
Line 569 ⟶ 1,061:
end
parse var x '.' fract /*parse number, get the fractional part*/
return length(fract) /*return number of fractional digits. */</
{{out|output|text= when using the default inputs:}}
<pre>
Line 587 ⟶ 1,079:
=={{header|Ring}}==
<
# Testing the function
decimals(2) # Unsensitive to the default setting of decimals
Line 608 ⟶ 1,100:
ok
end
</syntaxhighlight>
{{out}}
<pre>
4
</pre>
'''Another version'''
<syntaxhighlight lang="ring">
decimals(4)
num = 5.1945
strnum = string(num)
pos = substr(strnum,".")
dec = len(strnum) - pos
see "Number of decimals: " + dec + nl
</syntaxhighlight>
{{out}}
<pre>
Number of decimals: 4
</pre>
=={{header|RPL}}==
≪ DUP MANT →STR SIZE SWAP XPON - 2 - 0 MAX
≫ ''''NDEC'''' STO
≪ { 12 120 12.345 12.345677 1.23E-20 1.23E20 } → cases
≪ { } 1 cases SIZE '''FOR''' j
cases j GET '''NDEC''' + '''NEXT'''
≫ ≫ ''''TASK'''' STO
{{out}}
<pre>
1: { 0 0 3 6 22 0 }
</pre>
=={{header|Sidef}}==
<syntaxhighlight lang="ruby">func number_of_decimals(n, limit = 1e5) {
var prec = Num(Num!PREC)>>2
var prev = ''
n = Number(n) if !n.kind_of(Number)
loop {
var str = n.as_dec(prec)
if (prev == str) {
return (str.contains('.') ? str.substr(str.index('.')+1).len : 0)
}
prev = str
prec *= 2
return Inf if (prec > limit)
}
}
var list = [
9, 12.345, "12.3450", "12.345e53",
12.34555555555555555555, 0.1234567890987654321,
Num.pi, 1/3, 1.5**63
]
list.each {|n|
var c = number_of_decimals(n)
say "Number of decimals: #{'%3s' % c} Number: #{n}"
}</syntaxhighlight>
{{out}}
<pre>
Number of decimals: 0 Number: 9
Number of decimals: 3 Number: 12.345
Number of decimals: 3 Number: 12.3450
Number of decimals: 0 Number: 12.345e53
Number of decimals: 20 Number: 12.34555555555555555555
Number of decimals: 19 Number: 0.1234567890987654321
Number of decimals: 188 Number: 3.14159265358979323846264338327950288419716939938
Number of decimals: Inf Number: 0.333333333333333333333333333333333333333333333333
Number of decimals: 63 Number: 124093581919.6489476978273736503801880082242803382541751489
</pre>
Line 618 ⟶ 1,181:
Converting the fourth example to a Rat or BigRat object wouldn't help as the constructor for those classes automatically reduces the numerator and denominator to their lowest terms. BigRat would work for the fifth example but the argument would have to be passed as a string anyway so we might as well just parse the string.
<
var getNumDecimals = Fn.new { |n|
Line 641 ⟶ 1,204:
var ns = (n is String) ? "\"%(n)\"" : "%(n)"
System.print("%(ns) has %(d) decimals")
}</
{{out}}
|