awk high precision arithmetic












9















I am looking for a way to tell awk to do high-precision arithmetic in a substitution operation. This involves, reading a field from a file and substituting it with a 1% increment on that value. However, I am losing precision there. Here is a simplified reproduction of the problem:



 $ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {print}'
0.546748


Here, I have a 16 digit after decimal precision but awk gives only six. Using printf, I am getting the same result:



$ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {printf("%.16Gn", $1)}'
0.546748


Any suggestions on to how to get the desired precision?










share|improve this question

























  • Perhaps awk has higher resolution but it's just your output formatting is truncating. Use printf.

    – dubiousjim
    Nov 28 '12 at 15:25











  • No changes in result value after using printf. Question edited accordingly.

    – mkc
    Nov 28 '12 at 15:32











  • As @manatwork has pointed out, that gsub is unnecessary. The problem is gsub works on strings, not numbers, so a conversion is done first using CONVFMT, and the default value for that is %.6g.

    – jw013
    Nov 28 '12 at 15:46











  • @jw013, As I mentioned in the question, my original problem requires gsub since I need to substitute a number with a 1% increment. Agreed, in the simplified example, it is not required.

    – mkc
    Nov 28 '12 at 15:48
















9















I am looking for a way to tell awk to do high-precision arithmetic in a substitution operation. This involves, reading a field from a file and substituting it with a 1% increment on that value. However, I am losing precision there. Here is a simplified reproduction of the problem:



 $ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {print}'
0.546748


Here, I have a 16 digit after decimal precision but awk gives only six. Using printf, I am getting the same result:



$ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {printf("%.16Gn", $1)}'
0.546748


Any suggestions on to how to get the desired precision?










share|improve this question

























  • Perhaps awk has higher resolution but it's just your output formatting is truncating. Use printf.

    – dubiousjim
    Nov 28 '12 at 15:25











  • No changes in result value after using printf. Question edited accordingly.

    – mkc
    Nov 28 '12 at 15:32











  • As @manatwork has pointed out, that gsub is unnecessary. The problem is gsub works on strings, not numbers, so a conversion is done first using CONVFMT, and the default value for that is %.6g.

    – jw013
    Nov 28 '12 at 15:46











  • @jw013, As I mentioned in the question, my original problem requires gsub since I need to substitute a number with a 1% increment. Agreed, in the simplified example, it is not required.

    – mkc
    Nov 28 '12 at 15:48














9












9








9


1






I am looking for a way to tell awk to do high-precision arithmetic in a substitution operation. This involves, reading a field from a file and substituting it with a 1% increment on that value. However, I am losing precision there. Here is a simplified reproduction of the problem:



 $ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {print}'
0.546748


Here, I have a 16 digit after decimal precision but awk gives only six. Using printf, I am getting the same result:



$ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {printf("%.16Gn", $1)}'
0.546748


Any suggestions on to how to get the desired precision?










share|improve this question
















I am looking for a way to tell awk to do high-precision arithmetic in a substitution operation. This involves, reading a field from a file and substituting it with a 1% increment on that value. However, I am losing precision there. Here is a simplified reproduction of the problem:



 $ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {print}'
0.546748


Here, I have a 16 digit after decimal precision but awk gives only six. Using printf, I am getting the same result:



$ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {printf("%.16Gn", $1)}'
0.546748


Any suggestions on to how to get the desired precision?







awk arithmetic floating-point






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 28 '12 at 23:40









Gilles

530k12810631591




530k12810631591










asked Nov 28 '12 at 15:19









mkcmkc

5,82342742




5,82342742













  • Perhaps awk has higher resolution but it's just your output formatting is truncating. Use printf.

    – dubiousjim
    Nov 28 '12 at 15:25











  • No changes in result value after using printf. Question edited accordingly.

    – mkc
    Nov 28 '12 at 15:32











  • As @manatwork has pointed out, that gsub is unnecessary. The problem is gsub works on strings, not numbers, so a conversion is done first using CONVFMT, and the default value for that is %.6g.

    – jw013
    Nov 28 '12 at 15:46











  • @jw013, As I mentioned in the question, my original problem requires gsub since I need to substitute a number with a 1% increment. Agreed, in the simplified example, it is not required.

    – mkc
    Nov 28 '12 at 15:48



















  • Perhaps awk has higher resolution but it's just your output formatting is truncating. Use printf.

    – dubiousjim
    Nov 28 '12 at 15:25











  • No changes in result value after using printf. Question edited accordingly.

    – mkc
    Nov 28 '12 at 15:32











  • As @manatwork has pointed out, that gsub is unnecessary. The problem is gsub works on strings, not numbers, so a conversion is done first using CONVFMT, and the default value for that is %.6g.

    – jw013
    Nov 28 '12 at 15:46











  • @jw013, As I mentioned in the question, my original problem requires gsub since I need to substitute a number with a 1% increment. Agreed, in the simplified example, it is not required.

    – mkc
    Nov 28 '12 at 15:48

















Perhaps awk has higher resolution but it's just your output formatting is truncating. Use printf.

– dubiousjim
Nov 28 '12 at 15:25





Perhaps awk has higher resolution but it's just your output formatting is truncating. Use printf.

– dubiousjim
Nov 28 '12 at 15:25













No changes in result value after using printf. Question edited accordingly.

– mkc
Nov 28 '12 at 15:32





No changes in result value after using printf. Question edited accordingly.

– mkc
Nov 28 '12 at 15:32













As @manatwork has pointed out, that gsub is unnecessary. The problem is gsub works on strings, not numbers, so a conversion is done first using CONVFMT, and the default value for that is %.6g.

– jw013
Nov 28 '12 at 15:46





As @manatwork has pointed out, that gsub is unnecessary. The problem is gsub works on strings, not numbers, so a conversion is done first using CONVFMT, and the default value for that is %.6g.

– jw013
Nov 28 '12 at 15:46













@jw013, As I mentioned in the question, my original problem requires gsub since I need to substitute a number with a 1% increment. Agreed, in the simplified example, it is not required.

– mkc
Nov 28 '12 at 15:48





@jw013, As I mentioned in the question, my original problem requires gsub since I need to substitute a number with a 1% increment. Agreed, in the simplified example, it is not required.

– mkc
Nov 28 '12 at 15:48










2 Answers
2






active

oldest

votes


















11














$ echo 0.4970436865354813 | awk -v CONVFMT=%.17g '{gsub($1, $1*1.1)}; {print}'
0.54674805518902947


Or rather here:



$ echo 0.4970436865354813 | awk '{printf "%.17gn", $1*1.1}'
0.54674805518902947


is probably the best you can achieve. Use bc instead for arbitrary precision.



$ echo '0.4970436865354813 * 1.1' | bc -l
.54674805518902943





share|improve this answer


























  • If you want arbitrary precision in AWK you can use the -M flag and set the PREC value to a large number

    – Robert Benson
    Apr 3 '18 at 20:09






  • 3





    @RobertBenson, only with GNU awk and only with recent versions (4.1 or above, so not at the time that answer was written) and only when MPFR was enabled at compile time though.

    – Stéphane Chazelas
    Apr 3 '18 at 20:37





















1














For higher precision with (GNU) awk (with bignum compiled in) use:



$ echo '0.4970436865354813' | awk -M -v PREC=100 '{printf("%.18fn", $1)}'
0.497043686535481300


The PREC=100 means 100 bits instead of the default 53 bits.

If that awk is not available, use bc



$ echo '0.4970436865354813*1.1' | bc -l
.54674805518902943


Or you will need to learn to live with the inherent imprecision of floats.





In your original lines there are several issues:




  • A factor of 1.1 is 10% increase, not 1% (should be a 1.01 multiplier). I'll use 10%.


  • The conversion format from a string to a (floating) number is given by CONVFMT. Its default value is %.6g. That limits the values to 6 decimal digits (after the dot). That is applied to the result of the gsub change of $1.



    $ a='0.4970436865354813'
    $ echo "$a" | awk '{printf("%.16fn", $1*1.1)}'
    0.5467480551890295

    $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16fn", $1)}'
    0.5467480000000000



  • The printf format g removes trailing zeros:



    $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16gn", $1)}'
    0.546748

    $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.17gn", $1)}'
    0.54674800000000001


    Both issues could be solved with:



    $ echo "$a" | awk '{printf("%.17gn", $1*1.1)}'
    0.54674805518902947


    Or



    $ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1)}; {printf("%.17fn", $1)}'
    0.54674805518902947



But don't get the idea that this means higher precision. The internal number representation is still a float in double size. That means 53 bits of precision and with that you could only be sure of 15 correct decimal digits, even if many times up to 17 digits look correct. That's a mirage.



$ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1}; {printf("%.30fn", $1)}'
0.546748055189029469325134868996


The correct value is:



$ echo "scale=18; 0.4970436865354813 * 1.1" | bc
.54674805518902943


Which could be also calculated with (GNU) awk if the bignum library has been compiled in:



$ echo "$a" | awk -M -v PREC=100 -v CONVFMT=%.30g '{printf("%.30fn", $1)}'
0.497043686535481300000000000000





share|improve this answer























    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "106"
    };
    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: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    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%2funix.stackexchange.com%2fquestions%2f57006%2fawk-high-precision-arithmetic%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    11














    $ echo 0.4970436865354813 | awk -v CONVFMT=%.17g '{gsub($1, $1*1.1)}; {print}'
    0.54674805518902947


    Or rather here:



    $ echo 0.4970436865354813 | awk '{printf "%.17gn", $1*1.1}'
    0.54674805518902947


    is probably the best you can achieve. Use bc instead for arbitrary precision.



    $ echo '0.4970436865354813 * 1.1' | bc -l
    .54674805518902943





    share|improve this answer


























    • If you want arbitrary precision in AWK you can use the -M flag and set the PREC value to a large number

      – Robert Benson
      Apr 3 '18 at 20:09






    • 3





      @RobertBenson, only with GNU awk and only with recent versions (4.1 or above, so not at the time that answer was written) and only when MPFR was enabled at compile time though.

      – Stéphane Chazelas
      Apr 3 '18 at 20:37


















    11














    $ echo 0.4970436865354813 | awk -v CONVFMT=%.17g '{gsub($1, $1*1.1)}; {print}'
    0.54674805518902947


    Or rather here:



    $ echo 0.4970436865354813 | awk '{printf "%.17gn", $1*1.1}'
    0.54674805518902947


    is probably the best you can achieve. Use bc instead for arbitrary precision.



    $ echo '0.4970436865354813 * 1.1' | bc -l
    .54674805518902943





    share|improve this answer


























    • If you want arbitrary precision in AWK you can use the -M flag and set the PREC value to a large number

      – Robert Benson
      Apr 3 '18 at 20:09






    • 3





      @RobertBenson, only with GNU awk and only with recent versions (4.1 or above, so not at the time that answer was written) and only when MPFR was enabled at compile time though.

      – Stéphane Chazelas
      Apr 3 '18 at 20:37
















    11












    11








    11







    $ echo 0.4970436865354813 | awk -v CONVFMT=%.17g '{gsub($1, $1*1.1)}; {print}'
    0.54674805518902947


    Or rather here:



    $ echo 0.4970436865354813 | awk '{printf "%.17gn", $1*1.1}'
    0.54674805518902947


    is probably the best you can achieve. Use bc instead for arbitrary precision.



    $ echo '0.4970436865354813 * 1.1' | bc -l
    .54674805518902943





    share|improve this answer















    $ echo 0.4970436865354813 | awk -v CONVFMT=%.17g '{gsub($1, $1*1.1)}; {print}'
    0.54674805518902947


    Or rather here:



    $ echo 0.4970436865354813 | awk '{printf "%.17gn", $1*1.1}'
    0.54674805518902947


    is probably the best you can achieve. Use bc instead for arbitrary precision.



    $ echo '0.4970436865354813 * 1.1' | bc -l
    .54674805518902943






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Aug 21 '18 at 12:27









    Isaac

    11.4k11652




    11.4k11652










    answered Nov 28 '12 at 15:41









    Stéphane ChazelasStéphane Chazelas

    300k55564916




    300k55564916













    • If you want arbitrary precision in AWK you can use the -M flag and set the PREC value to a large number

      – Robert Benson
      Apr 3 '18 at 20:09






    • 3





      @RobertBenson, only with GNU awk and only with recent versions (4.1 or above, so not at the time that answer was written) and only when MPFR was enabled at compile time though.

      – Stéphane Chazelas
      Apr 3 '18 at 20:37





















    • If you want arbitrary precision in AWK you can use the -M flag and set the PREC value to a large number

      – Robert Benson
      Apr 3 '18 at 20:09






    • 3





      @RobertBenson, only with GNU awk and only with recent versions (4.1 or above, so not at the time that answer was written) and only when MPFR was enabled at compile time though.

      – Stéphane Chazelas
      Apr 3 '18 at 20:37



















    If you want arbitrary precision in AWK you can use the -M flag and set the PREC value to a large number

    – Robert Benson
    Apr 3 '18 at 20:09





    If you want arbitrary precision in AWK you can use the -M flag and set the PREC value to a large number

    – Robert Benson
    Apr 3 '18 at 20:09




    3




    3





    @RobertBenson, only with GNU awk and only with recent versions (4.1 or above, so not at the time that answer was written) and only when MPFR was enabled at compile time though.

    – Stéphane Chazelas
    Apr 3 '18 at 20:37







    @RobertBenson, only with GNU awk and only with recent versions (4.1 or above, so not at the time that answer was written) and only when MPFR was enabled at compile time though.

    – Stéphane Chazelas
    Apr 3 '18 at 20:37















    1














    For higher precision with (GNU) awk (with bignum compiled in) use:



    $ echo '0.4970436865354813' | awk -M -v PREC=100 '{printf("%.18fn", $1)}'
    0.497043686535481300


    The PREC=100 means 100 bits instead of the default 53 bits.

    If that awk is not available, use bc



    $ echo '0.4970436865354813*1.1' | bc -l
    .54674805518902943


    Or you will need to learn to live with the inherent imprecision of floats.





    In your original lines there are several issues:




    • A factor of 1.1 is 10% increase, not 1% (should be a 1.01 multiplier). I'll use 10%.


    • The conversion format from a string to a (floating) number is given by CONVFMT. Its default value is %.6g. That limits the values to 6 decimal digits (after the dot). That is applied to the result of the gsub change of $1.



      $ a='0.4970436865354813'
      $ echo "$a" | awk '{printf("%.16fn", $1*1.1)}'
      0.5467480551890295

      $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16fn", $1)}'
      0.5467480000000000



    • The printf format g removes trailing zeros:



      $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16gn", $1)}'
      0.546748

      $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.17gn", $1)}'
      0.54674800000000001


      Both issues could be solved with:



      $ echo "$a" | awk '{printf("%.17gn", $1*1.1)}'
      0.54674805518902947


      Or



      $ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1)}; {printf("%.17fn", $1)}'
      0.54674805518902947



    But don't get the idea that this means higher precision. The internal number representation is still a float in double size. That means 53 bits of precision and with that you could only be sure of 15 correct decimal digits, even if many times up to 17 digits look correct. That's a mirage.



    $ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1}; {printf("%.30fn", $1)}'
    0.546748055189029469325134868996


    The correct value is:



    $ echo "scale=18; 0.4970436865354813 * 1.1" | bc
    .54674805518902943


    Which could be also calculated with (GNU) awk if the bignum library has been compiled in:



    $ echo "$a" | awk -M -v PREC=100 -v CONVFMT=%.30g '{printf("%.30fn", $1)}'
    0.497043686535481300000000000000





    share|improve this answer




























      1














      For higher precision with (GNU) awk (with bignum compiled in) use:



      $ echo '0.4970436865354813' | awk -M -v PREC=100 '{printf("%.18fn", $1)}'
      0.497043686535481300


      The PREC=100 means 100 bits instead of the default 53 bits.

      If that awk is not available, use bc



      $ echo '0.4970436865354813*1.1' | bc -l
      .54674805518902943


      Or you will need to learn to live with the inherent imprecision of floats.





      In your original lines there are several issues:




      • A factor of 1.1 is 10% increase, not 1% (should be a 1.01 multiplier). I'll use 10%.


      • The conversion format from a string to a (floating) number is given by CONVFMT. Its default value is %.6g. That limits the values to 6 decimal digits (after the dot). That is applied to the result of the gsub change of $1.



        $ a='0.4970436865354813'
        $ echo "$a" | awk '{printf("%.16fn", $1*1.1)}'
        0.5467480551890295

        $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16fn", $1)}'
        0.5467480000000000



      • The printf format g removes trailing zeros:



        $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16gn", $1)}'
        0.546748

        $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.17gn", $1)}'
        0.54674800000000001


        Both issues could be solved with:



        $ echo "$a" | awk '{printf("%.17gn", $1*1.1)}'
        0.54674805518902947


        Or



        $ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1)}; {printf("%.17fn", $1)}'
        0.54674805518902947



      But don't get the idea that this means higher precision. The internal number representation is still a float in double size. That means 53 bits of precision and with that you could only be sure of 15 correct decimal digits, even if many times up to 17 digits look correct. That's a mirage.



      $ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1}; {printf("%.30fn", $1)}'
      0.546748055189029469325134868996


      The correct value is:



      $ echo "scale=18; 0.4970436865354813 * 1.1" | bc
      .54674805518902943


      Which could be also calculated with (GNU) awk if the bignum library has been compiled in:



      $ echo "$a" | awk -M -v PREC=100 -v CONVFMT=%.30g '{printf("%.30fn", $1)}'
      0.497043686535481300000000000000





      share|improve this answer


























        1












        1








        1







        For higher precision with (GNU) awk (with bignum compiled in) use:



        $ echo '0.4970436865354813' | awk -M -v PREC=100 '{printf("%.18fn", $1)}'
        0.497043686535481300


        The PREC=100 means 100 bits instead of the default 53 bits.

        If that awk is not available, use bc



        $ echo '0.4970436865354813*1.1' | bc -l
        .54674805518902943


        Or you will need to learn to live with the inherent imprecision of floats.





        In your original lines there are several issues:




        • A factor of 1.1 is 10% increase, not 1% (should be a 1.01 multiplier). I'll use 10%.


        • The conversion format from a string to a (floating) number is given by CONVFMT. Its default value is %.6g. That limits the values to 6 decimal digits (after the dot). That is applied to the result of the gsub change of $1.



          $ a='0.4970436865354813'
          $ echo "$a" | awk '{printf("%.16fn", $1*1.1)}'
          0.5467480551890295

          $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16fn", $1)}'
          0.5467480000000000



        • The printf format g removes trailing zeros:



          $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16gn", $1)}'
          0.546748

          $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.17gn", $1)}'
          0.54674800000000001


          Both issues could be solved with:



          $ echo "$a" | awk '{printf("%.17gn", $1*1.1)}'
          0.54674805518902947


          Or



          $ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1)}; {printf("%.17fn", $1)}'
          0.54674805518902947



        But don't get the idea that this means higher precision. The internal number representation is still a float in double size. That means 53 bits of precision and with that you could only be sure of 15 correct decimal digits, even if many times up to 17 digits look correct. That's a mirage.



        $ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1}; {printf("%.30fn", $1)}'
        0.546748055189029469325134868996


        The correct value is:



        $ echo "scale=18; 0.4970436865354813 * 1.1" | bc
        .54674805518902943


        Which could be also calculated with (GNU) awk if the bignum library has been compiled in:



        $ echo "$a" | awk -M -v PREC=100 -v CONVFMT=%.30g '{printf("%.30fn", $1)}'
        0.497043686535481300000000000000





        share|improve this answer













        For higher precision with (GNU) awk (with bignum compiled in) use:



        $ echo '0.4970436865354813' | awk -M -v PREC=100 '{printf("%.18fn", $1)}'
        0.497043686535481300


        The PREC=100 means 100 bits instead of the default 53 bits.

        If that awk is not available, use bc



        $ echo '0.4970436865354813*1.1' | bc -l
        .54674805518902943


        Or you will need to learn to live with the inherent imprecision of floats.





        In your original lines there are several issues:




        • A factor of 1.1 is 10% increase, not 1% (should be a 1.01 multiplier). I'll use 10%.


        • The conversion format from a string to a (floating) number is given by CONVFMT. Its default value is %.6g. That limits the values to 6 decimal digits (after the dot). That is applied to the result of the gsub change of $1.



          $ a='0.4970436865354813'
          $ echo "$a" | awk '{printf("%.16fn", $1*1.1)}'
          0.5467480551890295

          $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16fn", $1)}'
          0.5467480000000000



        • The printf format g removes trailing zeros:



          $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16gn", $1)}'
          0.546748

          $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.17gn", $1)}'
          0.54674800000000001


          Both issues could be solved with:



          $ echo "$a" | awk '{printf("%.17gn", $1*1.1)}'
          0.54674805518902947


          Or



          $ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1)}; {printf("%.17fn", $1)}'
          0.54674805518902947



        But don't get the idea that this means higher precision. The internal number representation is still a float in double size. That means 53 bits of precision and with that you could only be sure of 15 correct decimal digits, even if many times up to 17 digits look correct. That's a mirage.



        $ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1}; {printf("%.30fn", $1)}'
        0.546748055189029469325134868996


        The correct value is:



        $ echo "scale=18; 0.4970436865354813 * 1.1" | bc
        .54674805518902943


        Which could be also calculated with (GNU) awk if the bignum library has been compiled in:



        $ echo "$a" | awk -M -v PREC=100 -v CONVFMT=%.30g '{printf("%.30fn", $1)}'
        0.497043686535481300000000000000






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Aug 20 '18 at 22:07









        IsaacIsaac

        11.4k11652




        11.4k11652






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • 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%2funix.stackexchange.com%2fquestions%2f57006%2fawk-high-precision-arithmetic%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

            Morgemoulin

            Scott Moir

            Souastre