Currently dcc.Input only supports numbers with a dot decimal separator.
Input | Dash for Python Documentation | Plotly
This is a request for the feature that dcc.Input numbers also be accepted which a comma as decimal separator.
About 1.3 billion of the world’s population use comma as the decimal separator.
It might be related to ‘locale’ but could also be implemented just in dcc.Input itself.
Many years ago I wrote a (Pacsal / Delphi) routine that converts a string to a float, which would also accept strange inputs (like both = both thousand separator and decimal separator) as well as 1E3 = 1000 and so on. Here it is, just for inspiration:
{
REAL MATH ROUTINES
Created by : Claus Futtrup
Date : 3. April 1997 (24. August 1997 valid until 9/3-01)
Last modified : 12. June 2001
}
{DEFINE CHECK} { use various checking compiler-directives }
{DEFINE DEBUG} { use debugging compiler-directives }
{* Compiler directives *}
{$I OPTIONS.INC} { include this file }
interface
const { extended goes 3.4E-4932 to 1.1E4932}
exp_max = 308; { double = float goes from 5.0E-324 to 1.7E308 }
precision = 15; { and holds 15-16 digits }
e = 2.71828182846; { the number e }
type
float = double;
var
zero, inf : float; { zero or infinity numbers }
eps : float; { epsilon, a negligible small number }
function s2float(s : string; var flag : boolean) : float; { given string, returns a float }
implementation
function s2float(s : string; var flag : boolean) : float;
var
epos : byte; { position of E (or e), the exponential }
errorcode : integer;
the_number : float; { the converted number }
str : string; { temporary/local string }
i : byte; { counter }
j : byte; { counter }
begin
flag := true;
the_number := 0;
epos := 0;
i := 0;
j := 0;
for errorcode := 1 to length(s) do { use errorcode as counter }
begin
case s[errorcode] of { look for ... }
'E' : inc(epos);
'e' : inc(epos); { use epos as a counter }
'.' : inc(i);
',' : inc(j);
end;
end;
if (epos>1) OR ((i>1) AND (j>1)) then
flag := false
else { else number accepted, for now }
begin
if (epos=1) then { i E found, then }
begin
epos := pos('e',s); { examine number after E }
if (epos=0) then
epos := pos('E',s);
str := copy(s,epos+1,length(s));
if (pos(',',str)>0) OR (pos('.',str)>0) then
flag := false
else
begin
val(str,the_number,errorcode);
if errorcode <> 0 then { if conversion error }
flag := false
else if the_number>=exp_max then
the_number := inf { if very large, set to infinity }
else
the_number := 0; { else restore, exponential is accepted }
end;
end;
if flag AND (the_number=0) then { if exponential OK or no exponential }
begin
if (i=1) then
begin
if (j=1) then
begin
i := pos('.',s);
j := pos(',',s);
if (i<j) then { the first appearance is removed }
begin { because the last is assumed }
delete(s,i,1); { to be the decimal separator }
s[pos(',',s)] := '.'; { convert comma to dot }
end
else {j<i}
delete(s,j,1);
end
else if (j>1) then { remove all commas }
for i := 1 to j do
delete(s,pos(',',s),1);
end
else if j=1 then
begin
if i>1 then { remove all dots }
for j := 1 to i do
delete(s,pos('.',s),1);
s[pos(',',s)] := '.'; { convert comma to dot }
end;
val(s,the_number,errorcode);{ convert text string to number }
if errorcode <> 0 then { if conversion error(?) }
flag := false;
end;
end;
if (flag=false) then
begin
s2float := 0; { error in conversion }
end
else
s2float := the_number; { successful conversion or inf }
end;
With kind regards,
Claus