R numeric to char precision loss
I want to convert my many-digit numeric vector to character. I tried the following solutions here which works for one number but not for a vector. This is OK
options(digits=20)
options(scipen=99999)
x<-129483.19999999999709;format(round(x, 12), nsmall = 12)
[1] "129483.199999999997"
But this is not. how to keep numeric precision in characters for numeric vectors?
> y <- c(129483.19999999999709, 1.3546746874,687676846.2546746464)
Specially problematic is 687676846.2546746464
Also tried:
> specify_decimal(y, 12)
[1] "129483.199999999997" "1.354674687400" "687676846.254674673080"
> formatC(y, digits = 12, format = "f")
[1] "129483.199999999997" "1.354674687400" "687676846.254674673080"
> formattable(y, digits = 12, format = "f")
[1] 129483.199999999997 1.354674687400 687676846.254674673080
> sprintf(y, fmt='%#.12g')
[1] "129483.200000" "1.35467468740" "687676846.255"
> sprintf(y, fmt='%#.22g')
[1] "129483.1999999999970896" "1.354674687399999966075" "687676846.2546746730804"
Expected result:
[1] "129483.199999999997" "1.354674687400" "687676846.254674646400"
It seems that precision loss occurs once only, it is not repeated.
> require(dplyr)
> convert <- function(x) as.numeric(as.character(x))
> 687676846.2546746464 %>% convert
[1] 687676846.25467503
> 687676846.2546746464 %>% convert %>% convert %>% convert
[1] 687676846.25467503
Here I only have 5-digit precision, but more problematic I can't know beforehand what precision I am going to get..
r type-conversion precision
|
show 5 more comments
I want to convert my many-digit numeric vector to character. I tried the following solutions here which works for one number but not for a vector. This is OK
options(digits=20)
options(scipen=99999)
x<-129483.19999999999709;format(round(x, 12), nsmall = 12)
[1] "129483.199999999997"
But this is not. how to keep numeric precision in characters for numeric vectors?
> y <- c(129483.19999999999709, 1.3546746874,687676846.2546746464)
Specially problematic is 687676846.2546746464
Also tried:
> specify_decimal(y, 12)
[1] "129483.199999999997" "1.354674687400" "687676846.254674673080"
> formatC(y, digits = 12, format = "f")
[1] "129483.199999999997" "1.354674687400" "687676846.254674673080"
> formattable(y, digits = 12, format = "f")
[1] 129483.199999999997 1.354674687400 687676846.254674673080
> sprintf(y, fmt='%#.12g')
[1] "129483.200000" "1.35467468740" "687676846.255"
> sprintf(y, fmt='%#.22g')
[1] "129483.1999999999970896" "1.354674687399999966075" "687676846.2546746730804"
Expected result:
[1] "129483.199999999997" "1.354674687400" "687676846.254674646400"
It seems that precision loss occurs once only, it is not repeated.
> require(dplyr)
> convert <- function(x) as.numeric(as.character(x))
> 687676846.2546746464 %>% convert
[1] 687676846.25467503
> 687676846.2546746464 %>% convert %>% convert %>% convert
[1] 687676846.25467503
Here I only have 5-digit precision, but more problematic I can't know beforehand what precision I am going to get..
r type-conversion precision
2
as.numeric(as.character(129483.123456789)) == 129483.123456789
printsTRUE
. I think there are two issues here. First, what is printed to the console may not reflect the underlying precision. Second, your sample number is floating point, and due to rounding error there could be some issues there. If you check my example number, rounding won't be a problem.
– Tim Biegeleisen
Nov 13 '18 at 11:08
well, what about my number?
– gpier
Nov 13 '18 at 11:10
character strings should definitely show all the digits
– gpier
Nov 13 '18 at 11:11
2
Check here:stackoverflow.com/questions/3443687/…, I think this code will do for your case:x<-129483.19999999999709;format(round(x, 14), nsmall = 14)
– Antonis
Nov 13 '18 at 11:19
1
If you are doing this because you want to write a number to a text file in such a way that you can recover exactly the same number when you read the text file, perhaps you could convert it to its binary representation (abbreviated as hex).
– John Coleman
Nov 14 '18 at 15:28
|
show 5 more comments
I want to convert my many-digit numeric vector to character. I tried the following solutions here which works for one number but not for a vector. This is OK
options(digits=20)
options(scipen=99999)
x<-129483.19999999999709;format(round(x, 12), nsmall = 12)
[1] "129483.199999999997"
But this is not. how to keep numeric precision in characters for numeric vectors?
> y <- c(129483.19999999999709, 1.3546746874,687676846.2546746464)
Specially problematic is 687676846.2546746464
Also tried:
> specify_decimal(y, 12)
[1] "129483.199999999997" "1.354674687400" "687676846.254674673080"
> formatC(y, digits = 12, format = "f")
[1] "129483.199999999997" "1.354674687400" "687676846.254674673080"
> formattable(y, digits = 12, format = "f")
[1] 129483.199999999997 1.354674687400 687676846.254674673080
> sprintf(y, fmt='%#.12g')
[1] "129483.200000" "1.35467468740" "687676846.255"
> sprintf(y, fmt='%#.22g')
[1] "129483.1999999999970896" "1.354674687399999966075" "687676846.2546746730804"
Expected result:
[1] "129483.199999999997" "1.354674687400" "687676846.254674646400"
It seems that precision loss occurs once only, it is not repeated.
> require(dplyr)
> convert <- function(x) as.numeric(as.character(x))
> 687676846.2546746464 %>% convert
[1] 687676846.25467503
> 687676846.2546746464 %>% convert %>% convert %>% convert
[1] 687676846.25467503
Here I only have 5-digit precision, but more problematic I can't know beforehand what precision I am going to get..
r type-conversion precision
I want to convert my many-digit numeric vector to character. I tried the following solutions here which works for one number but not for a vector. This is OK
options(digits=20)
options(scipen=99999)
x<-129483.19999999999709;format(round(x, 12), nsmall = 12)
[1] "129483.199999999997"
But this is not. how to keep numeric precision in characters for numeric vectors?
> y <- c(129483.19999999999709, 1.3546746874,687676846.2546746464)
Specially problematic is 687676846.2546746464
Also tried:
> specify_decimal(y, 12)
[1] "129483.199999999997" "1.354674687400" "687676846.254674673080"
> formatC(y, digits = 12, format = "f")
[1] "129483.199999999997" "1.354674687400" "687676846.254674673080"
> formattable(y, digits = 12, format = "f")
[1] 129483.199999999997 1.354674687400 687676846.254674673080
> sprintf(y, fmt='%#.12g')
[1] "129483.200000" "1.35467468740" "687676846.255"
> sprintf(y, fmt='%#.22g')
[1] "129483.1999999999970896" "1.354674687399999966075" "687676846.2546746730804"
Expected result:
[1] "129483.199999999997" "1.354674687400" "687676846.254674646400"
It seems that precision loss occurs once only, it is not repeated.
> require(dplyr)
> convert <- function(x) as.numeric(as.character(x))
> 687676846.2546746464 %>% convert
[1] 687676846.25467503
> 687676846.2546746464 %>% convert %>% convert %>% convert
[1] 687676846.25467503
Here I only have 5-digit precision, but more problematic I can't know beforehand what precision I am going to get..
r type-conversion precision
r type-conversion precision
edited Nov 13 '18 at 21:03
gpier
asked Nov 13 '18 at 11:03
gpiergpier
1,0861513
1,0861513
2
as.numeric(as.character(129483.123456789)) == 129483.123456789
printsTRUE
. I think there are two issues here. First, what is printed to the console may not reflect the underlying precision. Second, your sample number is floating point, and due to rounding error there could be some issues there. If you check my example number, rounding won't be a problem.
– Tim Biegeleisen
Nov 13 '18 at 11:08
well, what about my number?
– gpier
Nov 13 '18 at 11:10
character strings should definitely show all the digits
– gpier
Nov 13 '18 at 11:11
2
Check here:stackoverflow.com/questions/3443687/…, I think this code will do for your case:x<-129483.19999999999709;format(round(x, 14), nsmall = 14)
– Antonis
Nov 13 '18 at 11:19
1
If you are doing this because you want to write a number to a text file in such a way that you can recover exactly the same number when you read the text file, perhaps you could convert it to its binary representation (abbreviated as hex).
– John Coleman
Nov 14 '18 at 15:28
|
show 5 more comments
2
as.numeric(as.character(129483.123456789)) == 129483.123456789
printsTRUE
. I think there are two issues here. First, what is printed to the console may not reflect the underlying precision. Second, your sample number is floating point, and due to rounding error there could be some issues there. If you check my example number, rounding won't be a problem.
– Tim Biegeleisen
Nov 13 '18 at 11:08
well, what about my number?
– gpier
Nov 13 '18 at 11:10
character strings should definitely show all the digits
– gpier
Nov 13 '18 at 11:11
2
Check here:stackoverflow.com/questions/3443687/…, I think this code will do for your case:x<-129483.19999999999709;format(round(x, 14), nsmall = 14)
– Antonis
Nov 13 '18 at 11:19
1
If you are doing this because you want to write a number to a text file in such a way that you can recover exactly the same number when you read the text file, perhaps you could convert it to its binary representation (abbreviated as hex).
– John Coleman
Nov 14 '18 at 15:28
2
2
as.numeric(as.character(129483.123456789)) == 129483.123456789
prints TRUE
. I think there are two issues here. First, what is printed to the console may not reflect the underlying precision. Second, your sample number is floating point, and due to rounding error there could be some issues there. If you check my example number, rounding won't be a problem.– Tim Biegeleisen
Nov 13 '18 at 11:08
as.numeric(as.character(129483.123456789)) == 129483.123456789
prints TRUE
. I think there are two issues here. First, what is printed to the console may not reflect the underlying precision. Second, your sample number is floating point, and due to rounding error there could be some issues there. If you check my example number, rounding won't be a problem.– Tim Biegeleisen
Nov 13 '18 at 11:08
well, what about my number?
– gpier
Nov 13 '18 at 11:10
well, what about my number?
– gpier
Nov 13 '18 at 11:10
character strings should definitely show all the digits
– gpier
Nov 13 '18 at 11:11
character strings should definitely show all the digits
– gpier
Nov 13 '18 at 11:11
2
2
Check here:stackoverflow.com/questions/3443687/…, I think this code will do for your case:
x<-129483.19999999999709;format(round(x, 14), nsmall = 14)
– Antonis
Nov 13 '18 at 11:19
Check here:stackoverflow.com/questions/3443687/…, I think this code will do for your case:
x<-129483.19999999999709;format(round(x, 14), nsmall = 14)
– Antonis
Nov 13 '18 at 11:19
1
1
If you are doing this because you want to write a number to a text file in such a way that you can recover exactly the same number when you read the text file, perhaps you could convert it to its binary representation (abbreviated as hex).
– John Coleman
Nov 14 '18 at 15:28
If you are doing this because you want to write a number to a text file in such a way that you can recover exactly the same number when you read the text file, perhaps you could convert it to its binary representation (abbreviated as hex).
– John Coleman
Nov 14 '18 at 15:28
|
show 5 more comments
1 Answer
1
active
oldest
votes
At the end I could do what I wanted using these functions. addtrailingzeroes
will add a number of zeroes after decimal to x.
nbdec <- function(x)
x1 <- as.character(x)
xsplit <- strsplit(x1,"\.")
xlength <- sapply(xsplit, function(d) nchar(d)[2])
xlength <- ifelse(is.na(xlength), 0, xlength)
return(xlength)
trailingzeroes <- function(x, dig)
res <- rep(NA, length(x))
for( i in 1:length(x))
if(!is.na(x[i])) res[i] <- paste0(rep(0,max(0,dig-nbdec(x[i]))), collapse="")
else res[i] <- ""
return(res)
trailingcommas <- function(x) ifelse(is.na(x), NA, ifelse(nbdec(x)==0, ".",""))
addtrailingzeroes <- function(x, digits)
return(ifelse(!is.na(x), paste0(x, trailingcommas(x), trailingzeroes(x, digits)),NA))
However to suppress inaccuracies and rounding mistakes, x has to be cropped first using roundnumerics.max
:
roundnumerics.max <- function(df, startdig=12)
for(icol in 1:ncol(df))
if( is.numeric(df[,icol]))
dig <- startdig
while(any(!as.numeric(as.character(df[,icol])) %==% df[,icol]))
dig <- dig-1
df[,icol] <- round(df[,icol], digits=dig)
if(dig==0)
break
pprint("ERROR: zero numeric accuracy")
pprint("Numeric accuracy for column ",icol," ", colnames(df)[icol], " is ", dig)
return(data.frame(df, stringsAsFactors = F))
This is slow and far from elegant... I still think it hard to believe that R has such an accuracy limitation to 16 significant digits, and adds inaccurate noise that causes divergences when you try to increase the digits
option...Without letting you know...
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53279593%2fr-numeric-to-char-precision-loss%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
At the end I could do what I wanted using these functions. addtrailingzeroes
will add a number of zeroes after decimal to x.
nbdec <- function(x)
x1 <- as.character(x)
xsplit <- strsplit(x1,"\.")
xlength <- sapply(xsplit, function(d) nchar(d)[2])
xlength <- ifelse(is.na(xlength), 0, xlength)
return(xlength)
trailingzeroes <- function(x, dig)
res <- rep(NA, length(x))
for( i in 1:length(x))
if(!is.na(x[i])) res[i] <- paste0(rep(0,max(0,dig-nbdec(x[i]))), collapse="")
else res[i] <- ""
return(res)
trailingcommas <- function(x) ifelse(is.na(x), NA, ifelse(nbdec(x)==0, ".",""))
addtrailingzeroes <- function(x, digits)
return(ifelse(!is.na(x), paste0(x, trailingcommas(x), trailingzeroes(x, digits)),NA))
However to suppress inaccuracies and rounding mistakes, x has to be cropped first using roundnumerics.max
:
roundnumerics.max <- function(df, startdig=12)
for(icol in 1:ncol(df))
if( is.numeric(df[,icol]))
dig <- startdig
while(any(!as.numeric(as.character(df[,icol])) %==% df[,icol]))
dig <- dig-1
df[,icol] <- round(df[,icol], digits=dig)
if(dig==0)
break
pprint("ERROR: zero numeric accuracy")
pprint("Numeric accuracy for column ",icol," ", colnames(df)[icol], " is ", dig)
return(data.frame(df, stringsAsFactors = F))
This is slow and far from elegant... I still think it hard to believe that R has such an accuracy limitation to 16 significant digits, and adds inaccurate noise that causes divergences when you try to increase the digits
option...Without letting you know...
add a comment |
At the end I could do what I wanted using these functions. addtrailingzeroes
will add a number of zeroes after decimal to x.
nbdec <- function(x)
x1 <- as.character(x)
xsplit <- strsplit(x1,"\.")
xlength <- sapply(xsplit, function(d) nchar(d)[2])
xlength <- ifelse(is.na(xlength), 0, xlength)
return(xlength)
trailingzeroes <- function(x, dig)
res <- rep(NA, length(x))
for( i in 1:length(x))
if(!is.na(x[i])) res[i] <- paste0(rep(0,max(0,dig-nbdec(x[i]))), collapse="")
else res[i] <- ""
return(res)
trailingcommas <- function(x) ifelse(is.na(x), NA, ifelse(nbdec(x)==0, ".",""))
addtrailingzeroes <- function(x, digits)
return(ifelse(!is.na(x), paste0(x, trailingcommas(x), trailingzeroes(x, digits)),NA))
However to suppress inaccuracies and rounding mistakes, x has to be cropped first using roundnumerics.max
:
roundnumerics.max <- function(df, startdig=12)
for(icol in 1:ncol(df))
if( is.numeric(df[,icol]))
dig <- startdig
while(any(!as.numeric(as.character(df[,icol])) %==% df[,icol]))
dig <- dig-1
df[,icol] <- round(df[,icol], digits=dig)
if(dig==0)
break
pprint("ERROR: zero numeric accuracy")
pprint("Numeric accuracy for column ",icol," ", colnames(df)[icol], " is ", dig)
return(data.frame(df, stringsAsFactors = F))
This is slow and far from elegant... I still think it hard to believe that R has such an accuracy limitation to 16 significant digits, and adds inaccurate noise that causes divergences when you try to increase the digits
option...Without letting you know...
add a comment |
At the end I could do what I wanted using these functions. addtrailingzeroes
will add a number of zeroes after decimal to x.
nbdec <- function(x)
x1 <- as.character(x)
xsplit <- strsplit(x1,"\.")
xlength <- sapply(xsplit, function(d) nchar(d)[2])
xlength <- ifelse(is.na(xlength), 0, xlength)
return(xlength)
trailingzeroes <- function(x, dig)
res <- rep(NA, length(x))
for( i in 1:length(x))
if(!is.na(x[i])) res[i] <- paste0(rep(0,max(0,dig-nbdec(x[i]))), collapse="")
else res[i] <- ""
return(res)
trailingcommas <- function(x) ifelse(is.na(x), NA, ifelse(nbdec(x)==0, ".",""))
addtrailingzeroes <- function(x, digits)
return(ifelse(!is.na(x), paste0(x, trailingcommas(x), trailingzeroes(x, digits)),NA))
However to suppress inaccuracies and rounding mistakes, x has to be cropped first using roundnumerics.max
:
roundnumerics.max <- function(df, startdig=12)
for(icol in 1:ncol(df))
if( is.numeric(df[,icol]))
dig <- startdig
while(any(!as.numeric(as.character(df[,icol])) %==% df[,icol]))
dig <- dig-1
df[,icol] <- round(df[,icol], digits=dig)
if(dig==0)
break
pprint("ERROR: zero numeric accuracy")
pprint("Numeric accuracy for column ",icol," ", colnames(df)[icol], " is ", dig)
return(data.frame(df, stringsAsFactors = F))
This is slow and far from elegant... I still think it hard to believe that R has such an accuracy limitation to 16 significant digits, and adds inaccurate noise that causes divergences when you try to increase the digits
option...Without letting you know...
At the end I could do what I wanted using these functions. addtrailingzeroes
will add a number of zeroes after decimal to x.
nbdec <- function(x)
x1 <- as.character(x)
xsplit <- strsplit(x1,"\.")
xlength <- sapply(xsplit, function(d) nchar(d)[2])
xlength <- ifelse(is.na(xlength), 0, xlength)
return(xlength)
trailingzeroes <- function(x, dig)
res <- rep(NA, length(x))
for( i in 1:length(x))
if(!is.na(x[i])) res[i] <- paste0(rep(0,max(0,dig-nbdec(x[i]))), collapse="")
else res[i] <- ""
return(res)
trailingcommas <- function(x) ifelse(is.na(x), NA, ifelse(nbdec(x)==0, ".",""))
addtrailingzeroes <- function(x, digits)
return(ifelse(!is.na(x), paste0(x, trailingcommas(x), trailingzeroes(x, digits)),NA))
However to suppress inaccuracies and rounding mistakes, x has to be cropped first using roundnumerics.max
:
roundnumerics.max <- function(df, startdig=12)
for(icol in 1:ncol(df))
if( is.numeric(df[,icol]))
dig <- startdig
while(any(!as.numeric(as.character(df[,icol])) %==% df[,icol]))
dig <- dig-1
df[,icol] <- round(df[,icol], digits=dig)
if(dig==0)
break
pprint("ERROR: zero numeric accuracy")
pprint("Numeric accuracy for column ",icol," ", colnames(df)[icol], " is ", dig)
return(data.frame(df, stringsAsFactors = F))
This is slow and far from elegant... I still think it hard to believe that R has such an accuracy limitation to 16 significant digits, and adds inaccurate noise that causes divergences when you try to increase the digits
option...Without letting you know...
answered Nov 14 '18 at 15:22
gpiergpier
1,0861513
1,0861513
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53279593%2fr-numeric-to-char-precision-loss%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
as.numeric(as.character(129483.123456789)) == 129483.123456789
printsTRUE
. I think there are two issues here. First, what is printed to the console may not reflect the underlying precision. Second, your sample number is floating point, and due to rounding error there could be some issues there. If you check my example number, rounding won't be a problem.– Tim Biegeleisen
Nov 13 '18 at 11:08
well, what about my number?
– gpier
Nov 13 '18 at 11:10
character strings should definitely show all the digits
– gpier
Nov 13 '18 at 11:11
2
Check here:stackoverflow.com/questions/3443687/…, I think this code will do for your case:
x<-129483.19999999999709;format(round(x, 14), nsmall = 14)
– Antonis
Nov 13 '18 at 11:19
1
If you are doing this because you want to write a number to a text file in such a way that you can recover exactly the same number when you read the text file, perhaps you could convert it to its binary representation (abbreviated as hex).
– John Coleman
Nov 14 '18 at 15:28