Skip to content

Conversation

reactormonk
Copy link
Contributor

This solves the trailing zero problem, but the ultimate solution would be to port ruby/python.

@Varriount
Copy link
Contributor

Have you written a unit test for this/checked whether this patch causes any unit tests to fail?

@reactormonk
Copy link
Contributor Author

Unit test yes, checked for failed tests, no.

@fowlmouth
Copy link
Contributor

wont this print garbage for 4 byte floats?

@dom96
Copy link
Contributor

dom96 commented Apr 27, 2014

Could someone just translate Ruby's or Python's float formatting implementation instead?

@fowlmouth
Copy link
Contributor

I take it back, %g is fine for float/double
@dom96 I'm pretty sure ruby uses %g, I checked and the behavior is the same

@dom96
Copy link
Contributor

dom96 commented Apr 28, 2014

@fowlmouth you sure? @reactormonk showed me some float formatting code from ruby and it looks a lot more complicated than just a %g

@fowlmouth
Copy link
Contributor

The behavior seems identical, they both switch to scientific notation as soon as it would be shorter than normal notation:

$ ruby -e "puts 0.00001, 0.0001"
1.0e-05
0.0001
$ cat t.c && gcc -o t t.c && ./t
#include"stdio.h"
int main(void)
{
float x = 0.00001;
float y = 0.0001;
printf("%%f %f %f\n", x, y);
printf("%%g %g %g\n", x, y);
return 0;
}
%f 0.000010 0.000100
%g 1e-05 0.0001

Python does the same

@Varriount
Copy link
Contributor

@reactormonk have you checked to see if this PR causes any current tests to fail?

@reactormonk
Copy link
Contributor Author

I found that $5.0 results in "5". I think that's one of the things that the ruby implementation changes.

@fowlmouth
Copy link
Contributor

@Araq
Copy link
Member

Araq commented May 31, 2014

$5.0 really should produce "5.0". Can you port Ruby's solution to Nimrod please?

@katlogic
Copy link

katlogic commented Jun 4, 2014

Perhaps do something ugly for now, like this:

proc c_sprintf(buf, frmt: cstring):int {.header: "<stdio.h>",
  importc: "sprintf", varargs, noSideEffect.}
proc to_s(f: float): string =
  var buf: array [0..64, char]
  var n:int = c_sprintf(buf, "%.16g", f)
  for i in 0..n-1:
    if buf[i] notin {'0'..'9','-'}:
      return $buf
  buf[n] = '.'
  buf[n+1] = '0'
  buf[n+2] = '\0'
  result = $buf

stdout.writeln(to_s(-0.00001))

Custom more flexible formatter would be cool for the whole formatBiggestFloat shebang.

EDIT: .0 Should be appended if result of %g consists only of 0..9 and -

@reactormonk
Copy link
Contributor Author

@Araq Hm, nope. Got ~500 LoC behind ruby_dtoa which contains a bunch of floating magic with a lot of special cases with a bunch of gotos and ifdefs for platforms. Too complicated imo.

@fowlmouth
Copy link
Contributor

I like @katlogic 's solution for the time being

@reactormonk
Copy link
Contributor Author

I did a bit more extensive solution that should have the same results as @katlogic's code, except it should be more robust in cases like 1.0e100.

@reactormonk
Copy link
Contributor Author

According to the standard, printf is influenced by locale, so this will break. So we need another solution.

@reactormonk reactormonk reopened this Jun 14, 2014
@katlogic
Copy link

Or make it even more horrible:

proc c_sprintf(buf, frmt: cstring):int {.header: "<stdio.h>", 
  importc: "sprintf", varargs, noSideEffect.}
proc c_localeconv():ptr cstring {.header: "<locale.h>", 
  importc: "localeconv", noSideEffect.}

proc to_s(f: float): string =
  var buf: array [0..64, char]
  var n = c_sprintf(buf, "%.16g", f)
  for i in 0..n-1:
    if buf[i] notin {'0'..'9','-'}:
      return $buf
  buf[n] = c_localeconv()[0]
  buf[n+1] = '0'
  buf[n+2] = '\0'
  result = $buf

stdout.writeln(to_s(0))

The comma vs dot is consistent with other places which uses c_sprintf so it's not that bad.

@reactormonk reactormonk deleted the float_$ branch June 5, 2015 16:06
Clyybber pushed a commit to Clyybber/Nim that referenced this pull request Feb 24, 2024
## Summary

On Windows Testament now correctly captures the exit code from commands
(compile, test run, etc).

## Details

On platforms like Windows closing a process before reading the exit code
invalidates the exit code, returning 0, which would falsely signify a
success.

Instead, use  `defer`  to make sure that the object is kept alive until
the end of scope.

---------

Co-authored-by: Saem Ghani <saemghani+github@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants