decimal.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package strconv
  2. import (
  3. "math"
  4. )
  5. // ParseDecimal parses number of the format 1.2
  6. func ParseDecimal(b []byte) (float64, int) {
  7. // float64 has up to 17 significant decimal digits and an exponent in [-1022,1023]
  8. i := 0
  9. //sign := 1.0
  10. //if 0 < len(b) && b[0] == '-' {
  11. // sign = -1.0
  12. // i++
  13. //}
  14. start := -1
  15. dot := -1
  16. n := uint64(0)
  17. for ; i < len(b); i++ {
  18. // parse up to 18 significant digits (with dot will be 17) ignoring zeros before/after
  19. c := b[i]
  20. if '0' <= c && c <= '9' {
  21. if start == -1 {
  22. if '1' <= c && c <= '9' {
  23. n = uint64(c - '0')
  24. start = i
  25. }
  26. } else if i-start < 18 {
  27. n *= 10
  28. n += uint64(c - '0')
  29. }
  30. } else if c == '.' {
  31. if dot != -1 {
  32. break
  33. }
  34. dot = i
  35. } else {
  36. break
  37. }
  38. }
  39. if i == 1 && dot == 0 {
  40. return 0.0, 0 // only dot
  41. } else if start == -1 {
  42. return 0.0, i // only zeros and dot
  43. } else if dot == -1 {
  44. dot = i
  45. }
  46. exp := (dot - start) - LenUint(n)
  47. if dot < start {
  48. exp++
  49. }
  50. if 1023 < exp {
  51. return math.Inf(1), i
  52. //if sign == 1.0 {
  53. // return math.Inf(1), i
  54. //} else {
  55. // return math.Inf(-1), i
  56. //}
  57. } else if exp < -1022 {
  58. return 0.0, i
  59. }
  60. f := float64(n) // sign * float64(n)
  61. if 0 <= exp && exp < 23 {
  62. return f * float64pow10[exp], i
  63. } else if 23 < exp && exp < 0 {
  64. return f / float64pow10[exp], i
  65. }
  66. return f * math.Pow10(exp), i
  67. }