Getting the number of decimal places: Difference between revisions

From Rosetta Code
Content added Content deleted
(Getting the number of decimals en FreeBASIC)
m (→‎{{header|Phix}}: use pygments)
 
(22 intermediate revisions by 12 users not shown)
Line 1: Line 1:
{{draft task}}
{{draft task}}
;Task:
;Task:
Write a program (function) to get the number of decimals in a given number.
Write a program (function) to get the number of decimal places in a given number.




Line 15: Line 15:
{{trans|Python}}
{{trans|Python}}


<lang 11l>F dec(n)
<syntaxhighlight lang="11l">F dec(n)
R I ‘.’ C n {n.split(‘.’).last.len} E 0
R I ‘.’ C n {n.split(‘.’).last.len} E 0


print(dec(‘12.345’))
print(dec(‘12.345’))
print(dec(‘12.3450’))</lang>
print(dec(‘12.3450’))</syntaxhighlight>


{{out}}
{{out}}
Line 29: Line 29:
=={{header|Action!}}==
=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
{{libheader|Action! Tool Kit}}
<lang Action!>INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit
<syntaxhighlight lang="action!">INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit


BYTE FUNC FindC(CHAR ARRAY s CHAR c)
BYTE FUNC FindC(CHAR ARRAY s CHAR c)
Line 100: Line 100:
ValR("1.E-10",r) Test(r)
ValR("1.E-10",r) Test(r)
ValR("1.23456789E10",r) Test(r)
ValR("1.23456789E10",r) Test(r)
RETURN</lang>
RETURN</syntaxhighlight>
{{out}}
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Getting_the_number_of_decimals.png Screenshot from Atari 8-bit computer]
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Getting_the_number_of_decimals.png Screenshot from Atari 8-bit computer]
Line 114: Line 114:
1.23456789E+10 has 0 decimals
1.23456789E+10 has 0 decimals
</pre>
</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}}==
=={{header|AutoHotkey}}==
<lang AutoHotkey>for i, v in [10, "10", 12.345, "12.345", 12.3450, "12.3450"]
<syntaxhighlight lang="autohotkey">for i, v in [10, "10", 12.345, "12.345", 12.3450, "12.3450"]
output .= v " has " StrLen(StrSplit(v, ".").2) " decimals.`n"
output .= v " has " StrLen(StrSplit(v, ".").2) " decimals.`n"
MsgBox % output</lang>
MsgBox % output</syntaxhighlight>
{{out}}
{{out}}
<pre>10 has 0 decimals.
<pre>10 has 0 decimals.
Line 128: Line 184:


=={{header|AWK}}==
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f GETTING_THE_NUMBER_OF_DECIMALS.AWK
# syntax: GAWK -f GETTING_THE_NUMBER_OF_DECIMALS.AWK
BEGIN {
BEGIN {
Line 139: Line 195:
exit(0)
exit(0)
}
}
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 150: Line 206:


=={{header|C}}==
=={{header|C}}==
<lang c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>
#include <string.h>


int findNumOfDec(double x) {
int findNumOfDec(const char *s) {
char buffer[128];
int pos = 0;
int pos, num;
while (s[pos] && s[pos++] != '.') {}
return strlen(s + pos);

sprintf(buffer, "%.14f", x);

pos = 0;
num = 0;
while (buffer[pos] != 0 && buffer[pos] != '.') {
pos++;
}
if (buffer[pos] != 0) {
pos++; // skip over the decimal
while (buffer[pos] != 0) {
pos++; // find the end of the string
}
pos--; //reverse past the null sentiel
while (buffer[pos] == '0') {
pos--; // reverse past any zeros
}
while (buffer[pos] != '.') {
num++;
pos--; // only count decimals from this point
}
}
return num;
}
}


void test(double x) {
void test(const char *s) {
int num = findNumOfDec(x);
int num = findNumOfDec(s);
printf("%f has %d decimals\n", x, num);
const char *p = num != 1 ? "s" : "";
printf("%s has %d decimal%s\n", s, num, p);
}
}


int main() {
int main() {
test(12.0);
test("12");
test(12.345);
test("12.0");
test(12.345555555555);
test("12.345");
test(12.3450);
test("12.345555555555");
test(12.34555555555555555555);
test("12.3450");
test(1.2345e+54);
test("12.34555555555555555555");
char str[64];
sprintf(str, "%f", 1.2345e+54);
test(str);
return 0;
return 0;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>12.000000 has 0 decimals
12.345000 has 3 decimals
12 has 0 decimals
12.345556 has 12 decimals
12.0 has 1 decimal
12.345000 has 3 decimals
12.345 has 3 decimals
12.345556 has 14 decimals
12.345555555555 has 12 decimals
12.3450 has 4 decimals
1234500000000000060751116919315055127939946206157864960.000000 has 0 decimals</pre>
12.34555555555555555555 has 20 decimals
1234500000000000060751116919315055127939946206157864960.000000 has 6 decimals
</pre>


=={{header|C++}}==
=={{header|C++}}==
{{trans|C}}
{{trans|C}}
<lang cpp>#include <iomanip>
<syntaxhighlight lang="cpp">#include <iostream>
#include <iostream>
#include <cstring>
#include <sstream>

int findNumOfDec(double x) {
std::stringstream ss;
ss << std::fixed << std::setprecision(14) << x;

auto s = ss.str();
auto pos = s.find('.');
if (pos == std::string::npos) {
return 0;
}

auto tail = s.find_last_not_of('0');


int findNumOfDec(const char *s) {
return tail - pos;
int pos = 0;
while (s[pos] && s[pos++] != '.') {}
return strlen(s + pos);
}
}


void test(double x) {
void test(const char *s) {
std::cout << x << " has " << findNumOfDec(x) << " decimals\n";
int num = findNumOfDec(s);
const char *p = num != 1 ? "s" : "";
std::cout << s << " has " << num << " decimal" << p << "\n";
}
}


int main() {
int main() {
test(12.0);
test("12");
test(12.345);
test("12.0");
test(12.345555555555);
test("12.345");
test(12.3450);
test("12.345555555555");
test(12.34555555555555555555);
test("12.3450");
test(1.2345e+54);
test("12.34555555555555555555");
char str[64];
sprintf(str, "%f", 1.2345e+54);
test(str);
return 0;
return 0;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>12 has 0 decimals
<pre>
12 has 0 decimals
12.0 has 1 decimal
12.345 has 3 decimals
12.345 has 3 decimals
12.3456 has 12 decimals
12.345555555555 has 12 decimals
12.345 has 3 decimals
12.3450 has 4 decimals
12.3456 has 14 decimals
12.34555555555555555555 has 20 decimals
1234500000000000060751116919315055127939946206157864960.000000 has 6 decimals
1.2345e+54 has 0 decimals</pre>
</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|FreeBASIC}}==
=={{header|FreeBASIC}}==
<lang freebasic>Function dec(n As Double) As Uinteger
<syntaxhighlight lang="freebasic">Function dec(n As Double) As Uinteger
Dim As String c = Str(n)
Dim As String c = Str(n)
Return Iif(Instr(c, "."), Len(Mid(c,Instr(c, ".")+1)), 0)
Return Iif(Instr(c, "."), Len(Mid(c,Instr(c, ".")+1)), 0)
Line 256: Line 328:
Print n(i); " has "; dec(n(i)); " decimals"
Print n(i); " has "; dec(n(i)); " decimals"
Next i
Next i
Sleep</lang>
Sleep</syntaxhighlight>
{{out}}
{{out}}
<pre> 7 has 0 decimals
<pre> 7 has 0 decimals
Line 263: Line 335:
12.345677 has 6 decimals
12.345677 has 6 decimals
0.142857142857142 has 15 decimals</pre>
0.142857142857142 has 15 decimals</pre>



=={{header|Go}}==
=={{header|Go}}==
{{trans|Wren}}
{{trans|Wren}}
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 328: Line 399:
}
}
}
}
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 340: Line 411:
</pre>
</pre>
=={{Header|Haskell}}==
=={{Header|Haskell}}==
<lang Haskell>decimal :: String -> Int
<syntaxhighlight lang="haskell">decimal :: String -> Int
decimal [] = 0
decimal [] = 0
decimal ('.':xs) = length xs
decimal ('.':xs) = length xs
Line 348: Line 419:
numDecimal = decimal . show
numDecimal = decimal . show


main = print . map numDecimal $ [12.0, 12.345, 12.3450, 12.345555555555, 12.34555555555555555555, 1.2345e+54]</lang>
main = print . map numDecimal $ [12.0, 12.345, 12.3450, 12.345555555555, 12.34555555555555555555, 1.2345e+54]</syntaxhighlight>
{{out}}
{{out}}
<pre>[1,3,3,12,15,7]</pre>
<pre>[1,3,3,12,15,7]</pre>
=={{header|Java}}==
=={{header|Java}}==
<syntaxhighlight lang="java">
<lang java>public static int findNumOfDec(double x){
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);
String str = String.valueOf(x);
if(str.endsWith(".0")) return 0;
if(str.endsWith(".0")) return 0;
else return (str.substring(str.indexOf('.')).length() - 1);
else return (str.substring(str.indexOf('.')).length() - 1);
}</lang>
}</syntaxhighlight>

=={{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}}==
=={{header|Julia}}==
<lang julia>function postprecision(str::String)
<syntaxhighlight lang="julia">function postprecision(str::String)
s = lowercase(str)
s = lowercase(str)
if 'e' in s
if 'e' in s
Line 380: Line 515:
println("$n has $(postprecision(n)) decimals.")
println("$n has $(postprecision(n)) decimals.")
end
end
</lang>{{out}}
</syntaxhighlight>{{out}}
<pre>
<pre>
0.00100 has 5 decimals.
0.00100 has 5 decimals.
Line 399: Line 534:
=={{header|Kotlin}}==
=={{header|Kotlin}}==
{{trans|Java}}
{{trans|Java}}
<lang scala>fun findNumOfDec(x: Double): Int {
<syntaxhighlight lang="scala">fun findNumOfDec(x: Double): Int {
val str = x.toString()
val str = x.toString()
if (str.endsWith(".0")) {
if (str.endsWith(".0")) {
Line 411: Line 546:
println("%f has %d decimals".format(n, findNumOfDec(n)))
println("%f has %d decimals".format(n, findNumOfDec(n)))
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>12.000000 has 0 decimals
<pre>12.000000 has 0 decimals
Line 419: Line 554:
12.345556 has 15 decimals
12.345556 has 15 decimals
1234500000000000000000000000000000000000000000000000000.000000 has 7 decimals</pre>
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}}==
=={{header|Perl}}==
Need pragma <code>bignum</code> to handle decimals beyond 15 digits.
Need pragma <code>bignum</code> to handle decimals beyond 15 digits.
<lang perl>use bignum;
<syntaxhighlight lang="perl">use bignum;


printf "Fractional precision: %2s Number: %s\n", length((split /\./, $_)[1]) // 0, $_
printf "Fractional precision: %2s Number: %s\n", length((split /\./, $_)[1]) // 0, $_
for 9, 12.345, <12.3450>, 0.1234567890987654321, 1/3, 1.5**63;</lang>
for 9, 12.345, <12.3450>, 0.1234567890987654321, 1/3, 1.5**63;</syntaxhighlight>
{{out}}
{{out}}
<pre>Fractional precision: 0 Number: 9
<pre>Fractional precision: 0 Number: 9
Line 435: Line 628:


=={{header|Phix}}==
=={{header|Phix}}==
<!--<lang Phix>(phixonline)-->
<!--(phixonline)-->
<syntaxhighlight lang="phix">
<span style="color: #008080;">constant</span> <span style="color: #000000;">fracfmt</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">machine_bits</span><span style="color: #0000FF;">()=</span><span style="color: #000000;">32</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"%.14g"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"%.18g"</span><span style="color: #0000FF;">)</span>
constant fracfmt = iff(machine_bits()=32?"%.14g":"%.18g")
<span style="color: #008080;">function</span> <span style="color: #000000;">num_decimals</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">o</span><span style="color: #0000FF;">)</span>
function num_decimals(object o)
<span style="color: #004080;">integer</span> <span style="color: #000000;">nd</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
integer nd = -1
<span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t</span>
string s, t
<span style="color: #008080;">if</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
if integer(o) then
<span style="color: #000000;">nd</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
nd = 0
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">o</span><span style="color: #0000FF;">)</span>
s = sprintf("%d",o)
<span style="color: #008080;">elsif</span> <span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
elsif atom(o) then
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%.19g"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">o</span><span style="color: #0000FF;">)</span>
s = sprintf("%.19g",o)
<span style="color: #000000;">o</span> <span style="color: #0000FF;">-=</span> <span style="color: #7060A8;">trunc</span><span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">)</span>
o -= trunc(o)
<span style="color: #008080;">if</span> <span style="color: #000000;">o</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
if o=0 then
<span style="color: #000000;">nd</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">else</span>
nd = 0
else
<span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fracfmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">o</span><span style="color: #0000FF;">)</span>
t = sprintf(fracfmt,o)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">elsif</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
elsif string(o) then
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">o</span>
s = o
<span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span>
t = s
<span style="color: #008080;">else</span>
else
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"unknown type"</span><span style="color: #0000FF;">)</span>
crash("unknown type")
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">if</span> <span style="color: #000000;">nd</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
if nd=-1 then
<span style="color: #004080;">integer</span> <span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'e'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
integer e = find('e',t)
<span style="color: #008080;">if</span> <span style="color: #000000;">e</span> <span style="color: #008080;">then</span>
if e then
<span style="color: #0000FF;">{</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">e</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">e</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$])}</span>
{t,e} = {t[1..e-1],to_number(t[e+1..$])}
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #004080;">integer</span> <span style="color: #000000;">dot</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
integer dot = find('.',t)
<span style="color: #000000;">nd</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dot</span><span style="color: #0000FF;">?</span><span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">dot</span><span style="color: #0000FF;">-</span><span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">):</span><span style="color: #7060A8;">max</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">))</span>
nd = iff(dot?max(length(t)-dot-e,0):max(-e,0))
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">shorten</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"digits"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
s = shorten(s,"digits",5)
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nd</span><span style="color: #0000FF;">}</span>
return {s,nd}
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
end function
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"0.00100"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0.00100</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">001.805</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12.345</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12.345555555555</span><span style="color: #0000FF;">,</span>
sequence tests = {"0.00100", 0.00100, 001.805, 1/3, 12, 12.345, 12.345555555555,
<span style="color: #008000;">"12.3450"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"12.34555555555555555555"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12.345e53</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1.2345e-08</span><span style="color: #0000FF;">,</span>
"12.3450", "12.34555555555555555555", 12.345e53, 1.2345e-08,
<span style="color: #008000;">"12.345e53"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"1.2345e-08"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"0.1234567890987654321"</span><span style="color: #0000FF;">,</span>
"12.345e53", "1.2345e-08", "0.1234567890987654321",
<span style="color: #008000;">"124093581919.648947697827373650380188008224280338254175148904323577880859375"</span><span style="color: #0000FF;">}</span>
"124093581919.648947697827373650380188008224280338254175148904323577880859375"}
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
for i=1 to length(tests) do
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%25s has %d decimals\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">num_decimals</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]))</span>
printf(1,"%25s has %d decimals\n",num_decimals(tests[i]))
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<!--</lang>-->
</syntaxhighlight>
{{out}}
{{out}}
32 bit
32 bit
Line 505: Line 699:
=={{header|Python}}==
=={{header|Python}}==
Treated as a function over a string representation of a number to allow the capturing of significant trailing zeros.
Treated as a function over a string representation of a number to allow the capturing of significant trailing zeros.
<lang python>In [6]: def dec(n):
<syntaxhighlight lang="python">In [6]: def dec(n):
...: return len(n.rsplit('.')[-1]) if '.' in n else 0
...: return len(n.rsplit('.')[-1]) if '.' in n else 0


Line 514: Line 708:
Out[8]: 4
Out[8]: 4


In [9]: </lang>
In [9]: </syntaxhighlight>




Or, defining a slightly less partial function, over a given number, rather than a string:
Or, defining a slightly less partial function, over a given number, rather than a string:


<lang python>'''Report the decimal counts in default stringifications.'''
<syntaxhighlight lang="python">'''Report the decimal counts in default stringifications.'''


import math
import math
Line 627: Line 821:
# MAIN ---
# MAIN ---
if __name__ == '__main__':
if __name__ == '__main__':
main()</lang>
main()</syntaxhighlight>
{{Out}}
{{Out}}
<pre>Decimal counts in stringifications of real and imaginary components:
<pre>Decimal counts in stringifications of real and imaginary components:
Line 652: Line 846:
want to retain them, you need to pass the value as a string. (As below.)
want to retain them, you need to pass the value as a string. (As below.)


<lang perl6>use Rat::Precise;
<syntaxhighlight lang="raku" line>use Rat::Precise;


printf "Fractional precision: %-2s || Number: %s\n", (.split('.')[1] // '').chars, $_
printf "Fractional precision: %-2s || Number: %s\n", (.split('.')[1] // '').chars, $_
for 9, 12.345, '12.3450', 0.1234567890987654321, (1.5**63).precise;
for 9, 12.345, '12.3450', 0.1234567890987654321, (1.5**63).precise;
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>Fractional precision: 0 || Number: 9
<pre>Fractional precision: 0 || Number: 9
Line 673: Line 867:


Any number specified in exponential notation is first converted to a whole or fractional integer &nbsp; (or an integer with scale), <br>and &nbsp;that&nbsp; number is then examined.
Any number specified in exponential notation is first converted to a whole or fractional integer &nbsp; (or an integer with scale), <br>and &nbsp;that&nbsp; number is then examined.
<lang rexx>/*REXX pgm counts number of decimal digits which are to the right of the decimal point. */
<syntaxhighlight lang="rexx">/*REXX pgm counts number of decimal digits which are to the right of the decimal point. */
numeric digits 1000 /*ensure enuf dec digs for calculations*/
numeric digits 1000 /*ensure enuf dec digs for calculations*/
@.=; /*initialize a stemmed array to nulls. */
@.=; /*initialize a stemmed array to nulls. */
Line 707: Line 901:
end
end
parse var x '.' fract /*parse number, get the fractional part*/
parse var x '.' fract /*parse number, get the fractional part*/
return length(fract) /*return number of fractional digits. */</lang>
return length(fract) /*return number of fractional digits. */</syntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
<pre>
Line 725: Line 919:


=={{header|Ring}}==
=={{header|Ring}}==
<lang ring>
<syntaxhighlight lang="ring">
# Testing the function
# Testing the function
decimals(2) # Unsensitive to the default setting of decimals
decimals(2) # Unsensitive to the default setting of decimals
Line 746: Line 940:
ok
ok
end
end
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
4
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>
</pre>


=={{header|Sidef}}==
=={{header|Sidef}}==
<lang ruby>func number_of_decimals(n, limit = 1e5) {
<syntaxhighlight lang="ruby">func number_of_decimals(n, limit = 1e5) {
var prec = Num(Num!PREC)>>2
var prec = Num(Num!PREC)>>2
var prev = ''
var prev = ''
Line 781: Line 1,002:
var c = number_of_decimals(n)
var c = number_of_decimals(n)
say "Number of decimals: #{'%3s' % c} Number: #{n}"
say "Number of decimals: #{'%3s' % c} Number: #{n}"
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 800: Line 1,021:


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.
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.
<lang ecmascript>var error = "Argument must be a number or a decimal numeric string."
<syntaxhighlight lang="wren">var error = "Argument must be a number or a decimal numeric string."


var getNumDecimals = Fn.new { |n|
var getNumDecimals = Fn.new { |n|
Line 823: Line 1,044:
var ns = (n is String) ? "\"%(n)\"" : "%(n)"
var ns = (n is String) ? "\"%(n)\"" : "%(n)"
System.print("%(ns) has %(d) decimals")
System.print("%(ns) has %(d) decimals")
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}

Latest revision as of 23:21, 19 April 2024

Getting the number of decimal places is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Write a program (function) to get the number of decimal places in a given number.


Examples
  •   for num = 12.345         decimals = 3,     and
  •   for num = 12.3450       decimals = 4


(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).

11l

Translation of: Python
F dec(n)
   R I ‘.’ C n {n.split(‘.’).last.len} E 0

print(dec(‘12.345’))
print(dec(‘12.3450’))
Output:
3
4

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
Output:

Screenshot from Atari 8-bit computer

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

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;
Output:
12.345     3
12.3450    4

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]
Output:
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

AutoHotkey

for i, v in [10, "10",  12.345, "12.345", 12.3450, "12.3450"]
	output .= v " has " StrLen(StrSplit(v, ".").2) " decimals.`n"
MsgBox % output
Output:
10 has 0 decimals.
10 has 0 decimals.
12.345 has 3 decimals.
12.345 has 3 decimals.
12.3450 has 4 decimals.
12.3450 has 4 decimals.

AWK

# syntax: GAWK -f GETTING_THE_NUMBER_OF_DECIMALS.AWK
BEGIN {
    n = split("10,1.,1.0,12.345,12.3450",arr,",")
    for (i=1; i<=n; i++) {
      s = arr[i]
      x = index(s,".")
      printf("%s has %d decimals\n",s,x?length(s)-x:x)
    }
    exit(0)
}
Output:
10 has 0 decimals
1. has 0 decimals
1.0 has 1 decimals
12.345 has 3 decimals
12.3450 has 4 decimals

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(const char *s) {
    int num = findNumOfDec(s);
    const char *p  = num != 1 ? "s" : "";
    printf("%s has %d decimal%s\n", s, num, p);
}

int main() {
    test("12");
    test("12.0");
    test("12.345");
    test("12.345555555555");
    test("12.3450");
    test("12.34555555555555555555");
    char str[64];
    sprintf(str, "%f", 1.2345e+54);
    test(str);
    return 0;
}
Output:
12 has 0 decimals
12.0 has 1 decimal
12.345 has 3 decimals
12.345555555555 has 12 decimals
12.3450 has 4 decimals
12.34555555555555555555 has 20 decimals
1234500000000000060751116919315055127939946206157864960.000000 has 6 decimals

C++

Translation of: C
#include <iostream>
#include <cstring>

int findNumOfDec(const char *s) {
    int pos = 0;
    while (s[pos] && s[pos++] != '.') {}
    return strlen(s + pos);
}

void test(const char *s) {
    int num = findNumOfDec(s);
    const char *p  = num != 1 ? "s" : "";
    std::cout << s << " has " << num << " decimal" << p << "\n";
}

int main() {
    test("12");
    test("12.0");
    test("12.345");
    test("12.345555555555");
    test("12.3450");
    test("12.34555555555555555555");
    char str[64];
    sprintf(str, "%f", 1.2345e+54);
    test(str);
    return 0;
}
Output:
12 has 0 decimals
12.0 has 1 decimal
12.345 has 3 decimals
12.345555555555 has 12 decimals
12.3450 has 4 decimals
12.34555555555555555555 has 20 decimals
1234500000000000060751116919315055127939946206157864960.000000 has 6 decimals

EasyLang

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 & " "
.
Output:
14 3 3 1 7 

F#

//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")
Output:
0
2
3
4
5

FreeBASIC

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
Output:
 7 has 0 decimals
 12 has 0 decimals
 12.345 has 3 decimals
 12.345677 has 6 decimals
 0.142857142857142 has 15 decimals

Go

Translation of: Wren
package main

import (
    "fmt"
    "log"
    "math"
    "strings"
)

var error = "Argument must be a numeric literal or a decimal numeric string."

func getNumDecimals(n interface{}) int {
    switch v := n.(type) {
    case int:
        return 0
    case float64:
        if v == math.Trunc(v) {
            return 0
        }
        s := fmt.Sprintf("%g", v)
        return len(strings.Split(s, ".")[1])
    case string:
        if v == "" {
            log.Fatal(error)
        }
        if v[0] == '+' || v[0] == '-' {
            v = v[1:]
        }
        for _, c := range v {
            if strings.IndexRune("0123456789.", c) == -1 {
                log.Fatal(error)
            }
        }
        s := strings.Split(v, ".")
        ls := len(s)
        if ls == 1 {
            return 0
        } else if ls == 2 {
            return len(s[1])
        } else {
            log.Fatal("Too many decimal points")
        }
    default:
        log.Fatal(error)
    }
    return 0
}

func main() {
    var a = []interface{}{12, 12.345, 12.345555555555, "12.3450", "12.34555555555555555555", 12.345e53}
    for _, n := range a {
        d := getNumDecimals(n)
        switch v := n.(type) {
        case string:
            fmt.Printf("%q has %d decimals\n", v, d)
        case float32, float64:
            fmt.Printf("%g has %d decimals\n", v, d)
        default:
            fmt.Printf("%d has %d decimals\n", v, d)
        }
    }
}
Output:
12 has 0 decimals
12.345 has 3 decimals
12.345555555555 has 12 decimals
"12.3450" has 4 decimals
"12.34555555555555555555" has 20 decimals
1.2345e+54 has 0 decimals

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]
Output:
[1,3,3,12,15,7]

Java

int decimalPlaces(double value) {
    String string = String.valueOf(value);
    return string.length() - (string.indexOf('.') + 1);
}

Or

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);
}

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.

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."
Output:

Using gojq:

12.345 has 4 decimal places but the computed value is 3
Bye.

Using jq post-1.6:

Bye.


Julia

function postprecision(str::String)
    s = lowercase(str)
    if 'e' in s
        s, ex = split(s, "e")
        expdig = parse(Int, ex)
    else
        expdig = 0
    end
    dig = something(findfirst('.', reverse(s)), 1) - 1 - expdig
    return dig > 0 ? dig : 0
end
 
postprecision(x::Integer) = 0  
postprecision(x::Real, max=22) = postprecision(string(round(Float64(x), digits=max)))
 
testnums = ["0.00100", 0.00100, 001.805, 1.0 / 3, 2//3, 12, 12.345, "12.3450", 
    "12.34555555555555555555", 1.2345e+54, 1.2345e-08, "1.2345e-08", π]
 
for n in testnums
    println("$n has $(postprecision(n)) decimals.")
end
Output:
0.00100 has 5 decimals.
0.001 has 3 decimals.
1.805 has 3 decimals.
0.3333333333333333 has 16 decimals.
2//3 has 16 decimals.
12 has 0 decimals.
12.345 has 3 decimals.
12.3450 has 4 decimals.
12.34555555555555555555 has 20 decimals.
1.2345e54 has 0 decimals.
1.2345e-8 has 12 decimals.
1.2345e-08 has 12 decimals.
π has 15 decimals.

Kotlin

Translation of: Java
fun findNumOfDec(x: Double): Int {
    val str = x.toString()
    if (str.endsWith(".0")) {
        return 0
    }
    return str.substring(str.indexOf('.')).length - 1
}

fun main() {
    for (n in listOf(12.0, 12.345, 12.345555555555, 12.3450, 12.34555555555555555555, 1.2345e+54)) {
        println("%f has %d decimals".format(n, findNumOfDec(n)))
    }
}
Output:
12.000000 has 0 decimals
12.345000 has 3 decimals
12.345556 has 12 decimals
12.345000 has 3 decimals
12.345556 has 15 decimals
1234500000000000000000000000000000000000000000000000000.000000 has 7 decimals

Lambdatalk

In lambdatalk numbers are words/strings, some operators, like "+,-,*,/,...", know what to do with words like "123".

A first answer could be

{W.length
  {S.rest   
   {S.replace \. by space in 12.3450}}}
-> 4

This is a better one, if considering that ending zeroes should not be considered as decimals

{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

Numbers can be of any size.

Mathematica/Wolfram Language

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"]
Output:
3
4
0
0
0
7

Perl

Need pragma bignum to handle decimals beyond 15 digits.

use bignum;

printf "Fractional precision: %2s  Number: %s\n", length((split /\./, $_)[1]) // 0, $_
    for 9, 12.345, <12.3450>, 0.1234567890987654321, 1/3, 1.5**63;
Output:
Fractional precision:  0  Number: 9
Fractional precision:  3  Number: 12.345
Fractional precision:  4  Number: 12.3450
Fractional precision: 19  Number: 0.1234567890987654321
Fractional precision: 40  Number: 0.3333333333333333333333333333333333333333
Fractional precision: 63  Number: 124093581919.648947697827373650380188008224280338254175148904323577880859375

Phix

constant fracfmt = iff(machine_bits()=32?"%.14g":"%.18g")
 
function num_decimals(object o)
    integer nd = -1
    string s, t
    if integer(o) then
        nd = 0
        s = sprintf("%d",o)
    elsif atom(o) then
        s = sprintf("%.19g",o)
        o -= trunc(o)
        if o=0 then
            nd = 0
        else
            t = sprintf(fracfmt,o)
        end if
    elsif string(o) then
        s = o
        t = s
    else
        crash("unknown type")
    end if
    if nd=-1 then
        integer e = find('e',t)
        if e then
            {t,e} = {t[1..e-1],to_number(t[e+1..$])}
        end if
        integer dot = find('.',t)
        nd = iff(dot?max(length(t)-dot-e,0):max(-e,0))
    end if
    s = shorten(s,"digits",5)
    return {s,nd}
end function
 
sequence tests = {"0.00100", 0.00100, 001.805, 1/3, 12, 12.345, 12.345555555555, 
                  "12.3450", "12.34555555555555555555", 12.345e53, 1.2345e-08, 
                  "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
Output:

32 bit

                  0.00100 has 5 decimals
                    0.001 has 3 decimals
                    1.805 has 3 decimals
       0.3333333333333333 has 14 decimals
                       12 has 0 decimals
                   12.345 has 3 decimals
          12.345555555555 has 12 decimals
                  12.3450 has 4 decimals
  12.34555555555555555555 has 20 decimals
               1.2345e+54 has 0 decimals
                1.2345e-8 has 12 decimals
                12.345e53 has 0 decimals
               1.2345e-08 has 12 decimals
    0.1234567890987654321 has 19 decimals
12409...59375 (76 digits) has 63 decimals

64 bit as above except

    0.3333333333333333333 has 18 decimals

Python

Treated as a function over a string representation of a number to allow the capturing of significant trailing zeros.

In [6]: def dec(n):
   ...:     return len(n.rsplit('.')[-1]) if '.' in n else 0

In [7]: dec('12.345')
Out[7]: 3

In [8]: dec('12.3450')
Out[8]: 4

In [9]:


Or, defining a slightly less partial function, over a given number, rather than a string:

'''Report the decimal counts in default stringifications.'''

import math


# decimalCount :: Num -> Either String (Int, Int)
def decimalCount(n):
    '''Either a message string, or a tuple
       giving the number of decimals in the default
       (repr) representations of the real
       (and any imaginary part) of the given number.
    '''
    # decimalLen :: Float -> Int
    def decimalLen(f):
        return len(repr(f).split('.')[-1])

    return Right(
        (0, 0) if isinstance(n, int) else (
            (decimalLen(n), 0)
        ) if isinstance(n, float) else (
            tuple(decimalLen(x) for x in [n.real, n.imag])
        )
    ) if isinstance(n, (float, complex, int)) else (
        Left(repr(n) + ' is not a float, complex or int')
    )


# -------------------------- TEST --------------------------
# main :: IO ()
def main():
    '''Counts of decimals in default stringifications of
       real (and any imaginary) components of various
       Python numeric values.
    '''
    print(fTable(
        'Decimal counts in stringifications of real and imaginary components:'
    )(repr)(
        either(identity)(repr)
    )(decimalCount)([
        7, 1.25, 1.23456e2,
        1 / 7,
        2 ** 0.5,
        math.pi, math.e,
        complex(1.23, 4.567),
        None
    ]))


# ------------------------ GENERIC -------------------------

# Left :: a -> Either a b
def Left(x):
    '''Constructor for an empty Either (option type) value
       with an associated string.
    '''
    return {'type': 'Either', 'Right': None, 'Left': x}


# Right :: b -> Either a b
def Right(x):
    '''Constructor for a populated Either (option type) value'''
    return {'type': 'Either', 'Left': None, 'Right': x}


# either :: (a -> c) -> (b -> c) -> Either a b -> c
def either(fl):
    '''The application of fl to e if e is a Left value,
       or the application of fr to e if e is a Right value.
    '''
    return lambda fr: lambda e: fl(e['Left']) if (
        None is e['Right']
    ) else fr(e['Right'])


# identity :: a -> a
def identity(x):
    '''The identity function.'''
    return x


# ------------------------ DISPLAY -------------------------

# fTable :: String -> (a -> String) ->
# (b -> String) -> (a -> b) -> [a] -> String
def fTable(s):
    '''Heading -> x display function -> fx display function ->
       f -> xs -> tabular string.
    '''
    def gox(xShow):
        def gofx(fxShow):
            def gof(f):
                def goxs(xs):
                    ys = [xShow(x) for x in xs]
                    w = max(map(len, ys))

                    def arrowed(x, y):
                        return y.rjust(w, ' ') + ' -> ' + fxShow(f(x))
                    return s + '\n' + '\n'.join(
                        map(arrowed, xs, ys)
                    )
                return goxs
            return gof
        return gofx
    return gox


# MAIN ---
if __name__ == '__main__':
    main()
Output:
Decimal counts in stringifications of real and imaginary components:
                  7 -> (0, 0)
               1.25 -> (2, 0)
            123.456 -> (3, 0)
0.14285714285714285 -> (17, 0)
 1.4142135623730951 -> (16, 0)
  3.141592653589793 -> (15, 0)
  2.718281828459045 -> (15, 0)
      (1.23+4.567j) -> (2, 3)
               None -> None is not a float, complex or int

Raku

Works with: Rakudo version 2020.07

Raku does not specifically have a "decimal" number type, however we can easily determine the fractional precision of a rational number. It is somewhat touchy-feely for floating point numbers; (what is the fractional precision for 2.45e-12?), it's pretty pointless for Integers; (zero, aalllways zero...), but Rats (rationals) are doable. Note that these are (mostly) actual numerics, not numeric strings. The exception is '12.3450'. That is a numeric string since actual numerics automatically truncate non-significant trailing zeros. If you want to retain them, you need to pass the value as a string. (As below.)

use Rat::Precise;

printf "Fractional precision: %-2s || Number: %s\n", (.split('.')[1] // '').chars, $_
    for 9, 12.345, '12.3450', 0.1234567890987654321, (1.5**63).precise;
Output:
Fractional precision: 0  || Number: 9
Fractional precision: 3  || Number: 12.345
Fractional precision: 4  || Number: 12.3450
Fractional precision: 19 || Number: 0.1234567890987654321
Fractional precision: 63 || Number: 124093581919.648947697827373650380188008224280338254175148904323577880859375


REXX

Since the REXX language stores numbers as strings,   the issue of trailing zeros is a moot point.
If the number (as specified) has trailing zeros, there are left intact.

I took it to mean that the number of decimal digits   past the decimal point   are to be counted and displayed.

Any number specified in exponential notation is first converted to a whole or fractional integer   (or an integer with scale),
and  that  number is then examined.

/*REXX pgm counts number of decimal digits which are to the right of the decimal point. */
numeric digits 1000                              /*ensure enuf dec digs for calculations*/
@.=;                                             /*initialize a stemmed array to nulls. */
parse arg @.1;  if @.1=''  then do;      #= 9    /*#:  is the number of default numbers.*/
                                @.1 = 12
                                @.2 = 12.345
                                @.3 = 12.345555555555
                                @.4 = 12.3450
                                @.5 = 12.34555555555555555555
                                @.6 = 1.2345e+54
                                @.7 = 1.2345e-54
                                @.8 = 0.1234567890987654321
                                @.9 = 1.5 ** 63  /*calculate  1.5  raised to 63rd power.*/
                                end
                           else #= 1             /*the # of numbers specified on the CL.*/

say 'fractional'
say ' decimals '  center("number", 75)
say '══════════'  copies("═", 75)

          do j=1  for #;    n= countDec(@.j)     /*obtain the number of fractional digs.*/
          say right(n, 5)   left('',4)  @.j      /*show # of fract. digits & original #.*/
          end   /*j*/
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
countDec: procedure; parse upper arg x           /*obtain a number from the invoker.    */
          if pos('E', x)>0  then do              /*handle if the number has an exponent.*/
                                 LX= length(x)           /*length of the original number*/
                                 parse var x 'E' expon   /*obtain the exponent.         */
                                 LE= length(LE)          /*the length of the exponent.  */
                                 numeric digits LX + LE  /*ensure enough decimal digits.*/
                                 x= format(x, , , 0)     /*REXX does the heavy lifting. */
                                 end
          parse var x '.' fract                  /*parse number, get the fractional part*/
          return length(fract)                   /*return number of fractional digits.  */
output   when using the default inputs:
fractional
 decimals                                    number
══════════ ═══════════════════════════════════════════════════════════════════════════
    0      12
    3      12.345
   12      12.345555555555
    4      12.3450
   20      12.34555555555555555555
    0      1.2345E+54
   58      1.2345E-54
   19      0.1234567890987654321
   63      124093581919.648947697827373650380188008224280338254175148904323577880859375

Ring

# Testing the function
	decimals(2)		# Unsensitive to the default setting of decimals
	n = 5.1945
	? NbrOfDecimals(n)	# Gives 4

func NbrOfDecimals(n)
	nTemp = 1
	nNbrOfDecimals = 0      
	while True
		if nNbrOfDecimals < 9
			nNbrOfDecimals++
			nTemp *= 10
			nTemp1 = n * nTemp - ceil( n * nTemp )
			if nTemp1 = 0
				return nNbrOfDecimals
			ok
		else
			raise("Acceeding the maximum number of 9 decimals!")
		ok
	end
Output:
4

Another version

decimals(4)
num = 5.1945
strnum = string(num)
pos = substr(strnum,".")
dec = len(strnum) - pos
see "Number of decimals: " + dec + nl
Output:
Number of decimals: 4

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
Output:
1: { 0 0 3 6 22 0 }

Sidef

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}"
}
Output:
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

Wren

In the following script, the fourth and fifth examples need to be expressed as strings to avoid getting the wrong answer. If we use numbers instead, trailing zeros will be automatically removed and the result will be rounded to 14 significant figures when stringified or printed.

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 error = "Argument must be a number or a decimal numeric string."

var getNumDecimals = Fn.new { |n|
    if (n is Num) {
        if (n.isInteger) return 0
        n = n.toString
    } else if (n is String) {
        if (n == "") Fiber.abort(error)
        if (n[0] == "+" || n[0] == "-") n = n[1..-1]
        if (!n.all { |c| "0123456789.".contains(c) }) Fiber.abort(error)
    } else {
        Fiber.abort(error)
    }
    var s = n.split(".")
    var c = s.count
    return (c == 1) ? 0 : (c == 2) ? s[1].count : Fiber.abort("Too many decimal points.")
}

var a = [12, 12.345, 12.345555555555, "12.3450", "12.34555555555555555555", 12.345e53]
for (n in a) {
    var d = getNumDecimals.call(n)
    var ns = (n is String) ? "\"%(n)\"" : "%(n)" 
    System.print("%(ns) has %(d) decimals")
}
Output:
12 has 0 decimals
12.345 has 3 decimals
12.345555555555 has 12 decimals
"12.3450" has 4 decimals
"12.34555555555555555555" has 20 decimals
1.2345e+54 has 0 decimals