Skip to content

Commit

Permalink
write_csv: Disable scientific notation for integers (#765)
Browse files Browse the repository at this point in the history
Large integer numbers are not properly handled by write_csv as they are saved in scientific notation losing precision.

Fixes #845
  • Loading branch information
zeehio authored and jimhester committed Nov 13, 2018
1 parent 69c9fd3 commit 213eb0e
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 2 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ you would pass `skip = 3`, now you only need to pass `skip = 2`.
integer values in the first 1000 (#645, #652).
* `read_*()` now converts string `file`s to UTF-8 before parsing, which is convenient for non-UTF-8 platforms
in most cases (#730, @yutannihilation).
* `write_csv()` writes integers up to 10^15 without scientific notation (#765, @zeehio)
* `read_*()` no longer throws a "length of NULL cannot be changed" warning when
trying to resize a skipped column (#750, #833).
* `read_*()` now handles non-ASCII paths properly with R >=3.5.0 on Windows (#838, @yutannihilation).
Expand Down
4 changes: 2 additions & 2 deletions src/grisu3.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,8 @@ int dtoa_grisu3(double v, char *dst)
// If grisu3 was not able to convert the number to a string, then use old sprintf (suboptimal).
if (!success) return sprintf(s2, "%.17g", v) + (int)(s2 - dst);

// handle whole numbers
if (d_exp >= 0 && d_exp <= 2) {
// handle whole numbers as integers if they are < 10^15
if (d_exp >= 0 && d_exp <= MAX(2, 15 - len)) {
while(d_exp-- > 0) s2[len++] = '0';
s2[len] = '\0';
return (int)(s2+len-dst);
Expand Down
22 changes: 22 additions & 0 deletions tests/testthat/test-write-delim.R
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,25 @@ test_that("write_csv can write to compressed files", {
expect_true(is_bz2_file(filename))
expect_equal(mt, read_csv(filename))
})


test_that("write_csv writes large integers without scientific notation #671", {
x <- data.frame(a = c(60150001022000, 60150001022001))
filename <- file.path(tempdir(), "test_large_integers.csv")
on.exit(unlink(filename))
write_csv(x, filename)
content <- read_file(filename)
expect_equal(content, "a\n60150001022000\n60150001022001\n")
})

test_that("write_csv writes large integers without scientific notation up to 1E15 #671", {
x <- data.frame(a = c(1E13, 1E14, 1E15, 1E16))
filename <- file.path(tempdir(), "test_large_integers2.csv")
on.exit(unlink(filename))
write_csv(x, filename)
content <- read_file(filename)
expect_equal(content, "a\n10000000000000\n100000000000000\n1e15\n1e16\n")
x_exp <- read_csv(filename, col_types = "d")
expect_equal(x$a, x_exp$a)
})

0 comments on commit 213eb0e

Please sign in to comment.