R numeric to char precision loss










0















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..










share|improve this question



















  • 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











  • 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















0















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..










share|improve this question



















  • 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











  • 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













0












0








0








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..










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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












  • 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





    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












  • 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












1 Answer
1






active

oldest

votes


















0














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...






share|improve this answer






















    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
    );



    );













    draft saved

    draft discarded


















    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









    0














    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...






    share|improve this answer



























      0














      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...






      share|improve this answer

























        0












        0








        0







        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...






        share|improve this answer













        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...







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 14 '18 at 15:22









        gpiergpier

        1,0861513




        1,0861513





























            draft saved

            draft discarded
















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            Use pre created SQLite database for Android project in kotlin

            Darth Vader #20

            Ondo