mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-21 14:55:24 +00:00
* refs #7717 roundtrip float to string * make parseFloat more correct * improve float tests * improve float tests * cleanup
This commit is contained in:
@@ -716,19 +716,23 @@ proc tenToThePowerOf(b: int): BiggestFloat =
|
||||
const
|
||||
IdentChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'}
|
||||
|
||||
# XXX use JS's native way here
|
||||
proc nimParseBiggestFloat(s: string, number: var BiggestFloat, start = 0): int {.
|
||||
compilerproc.} =
|
||||
var
|
||||
esign = 1.0
|
||||
sign = 1.0
|
||||
i = start
|
||||
exponent: int
|
||||
flags: int
|
||||
number = 0.0
|
||||
|
||||
proc parseFloatNative(a: string): float =
|
||||
let a2 = a.cstring
|
||||
asm """
|
||||
`result` = Number(`a2`);
|
||||
"""
|
||||
|
||||
#[
|
||||
xxx how come code like this doesn't give IndexDefect ?
|
||||
let z = s[10000] == 'a'
|
||||
]#
|
||||
proc nimParseBiggestFloat(s: string, number: var BiggestFloat, start: int): int {.compilerproc.} =
|
||||
var sign: bool
|
||||
var i = start
|
||||
if s[i] == '+': inc(i)
|
||||
elif s[i] == '-':
|
||||
sign = -1.0
|
||||
sign = true
|
||||
inc(i)
|
||||
if s[i] == 'N' or s[i] == 'n':
|
||||
if s[i+1] == 'A' or s[i+1] == 'a':
|
||||
@@ -741,51 +745,40 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat, start = 0): int {
|
||||
if s[i+1] == 'N' or s[i+1] == 'n':
|
||||
if s[i+2] == 'F' or s[i+2] == 'f':
|
||||
if s[i+3] notin IdentChars:
|
||||
number = Inf*sign
|
||||
number = if sign: -Inf else: Inf
|
||||
return i+3 - start
|
||||
return 0
|
||||
while s[i] in {'0'..'9'}:
|
||||
# Read integer part
|
||||
flags = flags or 1
|
||||
number = number * 10.0 + toFloat(ord(s[i]) - ord('0'))
|
||||
inc(i)
|
||||
while s[i] == '_': inc(i)
|
||||
# Decimal?
|
||||
if s[i] == '.':
|
||||
var hd = 1.0
|
||||
inc(i)
|
||||
while s[i] in {'0'..'9'}:
|
||||
# Read fractional part
|
||||
flags = flags or 2
|
||||
number = number * 10.0 + toFloat(ord(s[i]) - ord('0'))
|
||||
hd = hd * 10.0
|
||||
inc(i)
|
||||
while s[i] == '_': inc(i)
|
||||
number = number / hd # this complicated way preserves precision
|
||||
# Again, read integer and fractional part
|
||||
if flags == 0: return 0
|
||||
# Exponent?
|
||||
if s[i] in {'e', 'E'}:
|
||||
inc(i)
|
||||
if s[i] == '+':
|
||||
inc(i)
|
||||
elif s[i] == '-':
|
||||
esign = -1.0
|
||||
inc(i)
|
||||
if s[i] notin {'0'..'9'}:
|
||||
return 0
|
||||
while s[i] in {'0'..'9'}:
|
||||
exponent = exponent * 10 + ord(s[i]) - ord('0')
|
||||
inc(i)
|
||||
while s[i] == '_': inc(i)
|
||||
# Calculate Exponent
|
||||
let hd = tenToThePowerOf(exponent)
|
||||
if esign > 0.0: number = number * hd
|
||||
else: number = number / hd
|
||||
# evaluate sign
|
||||
number = number * sign
|
||||
result = i - start
|
||||
|
||||
var buf: string
|
||||
# we could also use an `array[char, N]` buffer to avoid reallocs, or
|
||||
# use a 2-pass algorithm that first computes the length.
|
||||
if sign: buf.add '-'
|
||||
template addInc =
|
||||
buf.add s[i]
|
||||
inc(i)
|
||||
template eatUnderscores =
|
||||
while s[i] == '_': inc(i)
|
||||
while s[i] in {'0'..'9'}: # Read integer part
|
||||
buf.add s[i]
|
||||
inc(i)
|
||||
eatUnderscores()
|
||||
if s[i] == '.': # Decimal?
|
||||
addInc()
|
||||
while s[i] in {'0'..'9'}: # Read fractional part
|
||||
addInc()
|
||||
eatUnderscores()
|
||||
# Again, read integer and fractional part
|
||||
if buf.len == ord(sign): return 0
|
||||
if s[i] in {'e', 'E'}: # Exponent?
|
||||
addInc()
|
||||
if s[i] == '+': inc(i)
|
||||
elif s[i] == '-': addInc()
|
||||
if s[i] notin {'0'..'9'}: return 0
|
||||
while s[i] in {'0'..'9'}:
|
||||
addInc()
|
||||
eatUnderscores()
|
||||
number = parseFloatNative(buf)
|
||||
result = i - start
|
||||
|
||||
# Workaround for IE, IE up to version 11 lacks 'Math.trunc'. We produce
|
||||
# 'Math.trunc' for Nim's ``div`` and ``mod`` operators:
|
||||
|
||||
Reference in New Issue
Block a user