あなたが間違っているのはparseFloat()
、人間向けの表記法で小数を表す文字列をフィードすることですが、地域に依存しないJavaScriptparseFloat()
数値リテラルに対応する標準形式のみを受け入れ、常に小数点としてドットを使用し、桁区切り。
さらに、すべての回答で使用されているこのparseFloat()
関数は、正しい入力として受け入れるものが多すぎて、ほとんどの場合、間違った入力を検出できません。
Input Result
'1Hello' 1
'1 and 2' 1
'1.2+3.4' 1.2
' 25 ' 25
より厳密に制御された動作を得るために、独自の解析関数を実装することをお勧めします。これが私のものです:
// Parse a decimal fraction with specified thousands
// and group separators:
function /* number */ parse_float
( /* string */ s , // string to parse
/* string */ thousep, // thousands separator, empty string if none
/* string */ decsep // decimal separator , empty string if none
)
{ var /* integer */ whole, frac ; // whole and fractinal parts
var /* integer */ wnext, fnext; // position of next char after parse
var /* integer */ fraclen ; // length of fractional part
var /* integer */ ofs ; // offset of the first digit
var /* boolean */ done ; // entire string scanned?
var /* integer */ sign ; // sign of result
var /* number */ res ; // result
/* labels */ end: { whole: {
// Check parameter types and availability:
req_param( 's' , s , 'string' );
req_param( 'thousep', thousep, 'string' );
req_param( 'decsep' , decsep , 'string' );
frac = 0;
fraclen = 0;
res = NaN;
// Account for a possible sign:
switch( s.charAt(0) )
{ case '-': sign = -1; ofs = 1; break;
case '+': sign = +1; ofs = 1; break;
default : sign = +1; ofs = 0; break;
}
[done, wnext, whole] = parse_int_ts( s, ofs, thousep );
if( isNaN( whole ) ) break end;
if( done ) break whole;
if( s.charAt( wnext ) !== decsep ) break end;
[done, fnext, frac] = parse_int( s, 0, wnext + 1 );
if( !done ) break end;
fraclen = fnext - wnext - 1;
if( fraclen === 0 ) break end;
} /* whole: */ res = ( whole + frac / Math.pow( 10, fraclen ) ) * sign;
} /* end: */ return res;
}
// Require that a value be specified and have the expected type:
function req_param( /* string */ param, /* variant */ val, /* string */ type )
{ var /* string */ errmsg;
errmsg = ''; if( val === undefined ) errmsg = 'is undefined';
else if( val === null ) errmsg = 'is null';
else if( typeof val !== type ) errmsg = `must of type \`${type}'`;
if( errmsg !== '' ) // there has been an error
{ throw new Error(`Parameter \`${param}' ${errmsg}.`); }
}
// Parse an integer with a specified thousands separator:
function /* object[] */ parse_int_ts
( /* string */ s , // input string
/* integer */ start, // start position
/* character */ sep , // thousands separator
)
// Returns an array of:
// 0: boolean -- entire string was scanned
// 1: integer -- index of next character to scan
// 2: integer -- resulting inteer
{ var /* boolean */ full;
var /* integer */ next;
var /* integer */ res;
var /* integer */ len;
var /* integer */ psep;
var /* integer */ result;
res = 0;
psep = 0;
while( true )
{ result = NaN; // mark an error
[full, next, res] = parse_int( s, res, start );
len = next - start;
if( len === 0 ) break; // nothing parsed
if( sep !== '' )
{ if( psep > 0 && len !== 3 ) break; // non-first group not 3 digits
if( psep === 0 && len > 3 ) break; // first group longer than 3 digits
}
result = res; // mark success
if( s.charAt(next) !== sep ) break;
if( full ) break;
start = next;
psep = next;
start = start + 1;
}
return [full, next, result];
}
// Parse a compact of digits beginning at position `start'
// in string `s' as an integer number:
function /* object[]*/ parse_int
( /* string */ s , // input string
/* integer */ init, // initial value
/* integer */ start // start position in `s'
)
// Returns an array of:
// 0: boolean -- entire string was scanned
// 1: integer -- index of next character to scan
// 2: integer -- result
{ const /* integer */ ASCII_0 = 48;
var /* boolean */ full; // \
var /* integer */ next; // > the return value
var /* integer */ res ; // /
var /* integer */ n, i; // string length and current position
var /* integer */ code; // character code
n = s.length;
full = true;
next = n;
res = init;
for( i = start; i < n; i += 1 )
{ code = s.charCodeAt(i);
if( code < ASCII_0 || code >= ASCII_0 + 10 )
{ next = i;
full = false;
break;
}
res = res * 10 + code - ASCII_0;
}
if( code === undefined ) res = NaN;
return [ full, next, res ];
}
parse_float()
そして、フォーマットの数値を解析するために使用するテスト プログラム:
function test( /* string */ s )
{ var res;
res = parse_float( s, ' ', ',' );
console.log(`${(' ' + `[${s}]`).slice(-12)} => ${res}`);
}
test( '' );
test( '12' );
test( '12a' );
test( '12,' );
test( '12,345' );
test( '12 345' );
test( '123 45' );
test( '1 234 567' );
test( '12 345 56' );
test( '12345' );
test( '12 435,678' );
test( '+1,2' );
test( '-2 345' );
それは書いています:
[] => NaN
[12] => 12
[12a] => NaN
[12,] => NaN
[12,345] => 12.345
[12 345] => 12345
[123 45] => NaN
[1 234 567] => 1234567
[12 345 56] => NaN
[12345] => NaN
[12 435,678] => 12435.678
[+1,2] => 1.2
[-2 345] => -2345