formatfloat.nim 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2019 Nim contributors
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>",
  10. importc: "sprintf", varargs, noSideEffect.}
  11. proc writeToBuffer(buf: var array[65, char]; value: cstring) =
  12. var i = 0
  13. while value[i] != '\0':
  14. buf[i] = value[i]
  15. inc i
  16. proc writeFloatToBuffer*(buf: var array[65, char]; value: BiggestFloat): int =
  17. ## This is the implementation to format floats in the Nim
  18. ## programming language. The specific format for floating point
  19. ## numbers is not specified in the Nim programming language and
  20. ## might change slightly in the future, but at least wherever you
  21. ## format a float, it should be consistent.
  22. ##
  23. ## returns the amount of bytes written to `buf` not counting the
  24. ## terminating '\0' character.
  25. ##
  26. ## * `buf` - A buffer to write into. The buffer does not need to be
  27. ## initialized and it will be overridden.
  28. ##
  29. var n: int = c_sprintf(addr buf, "%.16g", value)
  30. var hasDot = false
  31. for i in 0..n-1:
  32. if buf[i] == ',':
  33. buf[i] = '.'
  34. hasDot = true
  35. elif buf[i] in {'a'..'z', 'A'..'Z', '.'}:
  36. hasDot = true
  37. if not hasDot:
  38. buf[n] = '.'
  39. buf[n+1] = '0'
  40. buf[n+2] = '\0'
  41. result = n + 2
  42. else:
  43. result = n
  44. # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN' or 'nan(ind)'
  45. # of '-1.#IND' are produced.
  46. # We want to get rid of these here:
  47. if buf[n-1] in {'n', 'N', 'D', 'd', ')'}:
  48. writeToBuffer(buf, "nan")
  49. result = 3
  50. elif buf[n-1] == 'F':
  51. if buf[0] == '-':
  52. writeToBuffer(buf, "-inf")
  53. result = 4
  54. else:
  55. writeToBuffer(buf, "inf")
  56. result = 3