Why is my arithmetic with a long long int behaving this way?Why is “using namespace std” considered bad practice?Why isnt int pow(int base, int exponent) in the standard C++ libraries?Why use static_cast<int>(x) instead of (int)x?Why can templates only be implemented in the header file?What does the C++ standard state the size of int, long type to be?What is the difference between const int*, const int * const, and int const *?Why is “using namespace std” considered bad practice?Easiest way to convert int to string in C++Why are elementwise additions much faster in separate loops than in a combined loop?Why is reading lines from stdin much slower in C++ than Python?Why is it faster to process a sorted array than an unsorted array?Why should I use a pointer rather than the object itself?

Is there any optimization for thread safety in for loop of Java?

Why did Gendry call himself Gendry Rivers?

Musical Shape on music stand

How does jetBlue determine its boarding order?

Test whether a string is in a list with variable

Average of samples in a period of time

Picking a theme as a discovery writer

Translation of "invincible independence"

How could a humanoid creature completely form within the span of 24 hours?

When does WordPress.org notify sites of new version?

Which "exotic salt" can lower water's freezing point by 70 °C?

Crime rates in a post-scarcity economy

Why were the rules for Proliferate changed?

Is throwing dice a stochastic or a deterministic process?

How can I test a shell script in a "safe environment" to avoid harm to my computer?

Employee is self-centered and affects the team negatively

Bash prompt takes only the first word of a hostname before the dot

What detail can Hubble see on Mars?

Can I use LPGL3 for library and Apache 2 for "main()"?

How to get the decimal part of a number in apex

Convert Numbers To Emoji Math

What chord could the notes 'F A♭ E♭' form?

GitLab account hacked and repo wiped

How do I minimise waste on a flight?



Why is my arithmetic with a long long int behaving this way?


Why is “using namespace std” considered bad practice?Why isnt int pow(int base, int exponent) in the standard C++ libraries?Why use static_cast<int>(x) instead of (int)x?Why can templates only be implemented in the header file?What does the C++ standard state the size of int, long type to be?What is the difference between const int*, const int * const, and int const *?Why is “using namespace std” considered bad practice?Easiest way to convert int to string in C++Why are elementwise additions much faster in separate loops than in a combined loop?Why is reading lines from stdin much slower in C++ than Python?Why is it faster to process a sorted array than an unsorted array?Why should I use a pointer rather than the object itself?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








17















I'm trying to calculate large integers with the long long datatype but when it gets large enough (2^55), the arithmetic behavior is unpredictable. I am working in Microsoft Visual Studio 2017.



In this first case, I am subtracting 2 from the long long variable m in the initialization. This works fine for all n until I try 54, then m will simply not be subtracted by 2.



#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <set>

using namespace std;

#define LL long long

int main()

LL n;
cin >> n;
LL m = pow(2, n + 1) - 2;
cout << m;
return 0;



However, using this code m does get subtracted by 2 and is working as I would expect.



#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <set>

using namespace std;

#define LL long long

int main()

LL n;
cin >> n;
LL m = pow(2, n + 1);
m -= 2;
cout << m;
return 0;



I expect both codes to be equivalent, why is this not the case?










share|improve this question









New contributor



Edvin K is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.














  • 24





    I'm curious where you picked up #define LL long long. I see it pretty often on this site, but I'm not aware of who or what is propagating it. Edit : Is it another one of those code golf habits?

    – François Andrieux
    May 3 at 13:54







  • 12





    using namespace std; is considered bad practice.

    – L. F.
    May 3 at 13:55






  • 22





    @Lucas but using LL = long long is also compile time, same size to type, and better. There is no reason to use a macro there

    – Guillaume Racicot
    May 3 at 14:04







  • 20





    @pipe: We understand perfectly well why. We don't want to promote bad practices just because you think it's "magically fine" for code examples. There are plenty of code examples on this site that were broken by using namespace std;

    – Mooing Duck
    May 3 at 16:56






  • 10





    @ThomasMatthews when you're telling people to prefer bit-shift for signed integer types, please alert them that for signed integer types overflow is undefined behavior, that this is not just theoretical undefined behavior but can create actual bugs on common compilers like gcc, and that the numerical result can be surprising and unexpected if you don't consciously think about overflow even when it is compiled to behave exactly as expected for a fixed-width integer type.

    – mtraceur
    May 3 at 21:13

















17















I'm trying to calculate large integers with the long long datatype but when it gets large enough (2^55), the arithmetic behavior is unpredictable. I am working in Microsoft Visual Studio 2017.



In this first case, I am subtracting 2 from the long long variable m in the initialization. This works fine for all n until I try 54, then m will simply not be subtracted by 2.



#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <set>

using namespace std;

#define LL long long

int main()

LL n;
cin >> n;
LL m = pow(2, n + 1) - 2;
cout << m;
return 0;



However, using this code m does get subtracted by 2 and is working as I would expect.



#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <set>

using namespace std;

#define LL long long

int main()

LL n;
cin >> n;
LL m = pow(2, n + 1);
m -= 2;
cout << m;
return 0;



I expect both codes to be equivalent, why is this not the case?










share|improve this question









New contributor



Edvin K is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.














  • 24





    I'm curious where you picked up #define LL long long. I see it pretty often on this site, but I'm not aware of who or what is propagating it. Edit : Is it another one of those code golf habits?

    – François Andrieux
    May 3 at 13:54







  • 12





    using namespace std; is considered bad practice.

    – L. F.
    May 3 at 13:55






  • 22





    @Lucas but using LL = long long is also compile time, same size to type, and better. There is no reason to use a macro there

    – Guillaume Racicot
    May 3 at 14:04







  • 20





    @pipe: We understand perfectly well why. We don't want to promote bad practices just because you think it's "magically fine" for code examples. There are plenty of code examples on this site that were broken by using namespace std;

    – Mooing Duck
    May 3 at 16:56






  • 10





    @ThomasMatthews when you're telling people to prefer bit-shift for signed integer types, please alert them that for signed integer types overflow is undefined behavior, that this is not just theoretical undefined behavior but can create actual bugs on common compilers like gcc, and that the numerical result can be surprising and unexpected if you don't consciously think about overflow even when it is compiled to behave exactly as expected for a fixed-width integer type.

    – mtraceur
    May 3 at 21:13













17












17








17


1






I'm trying to calculate large integers with the long long datatype but when it gets large enough (2^55), the arithmetic behavior is unpredictable. I am working in Microsoft Visual Studio 2017.



In this first case, I am subtracting 2 from the long long variable m in the initialization. This works fine for all n until I try 54, then m will simply not be subtracted by 2.



#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <set>

using namespace std;

#define LL long long

int main()

LL n;
cin >> n;
LL m = pow(2, n + 1) - 2;
cout << m;
return 0;



However, using this code m does get subtracted by 2 and is working as I would expect.



#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <set>

using namespace std;

#define LL long long

int main()

LL n;
cin >> n;
LL m = pow(2, n + 1);
m -= 2;
cout << m;
return 0;



I expect both codes to be equivalent, why is this not the case?










share|improve this question









New contributor



Edvin K is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











I'm trying to calculate large integers with the long long datatype but when it gets large enough (2^55), the arithmetic behavior is unpredictable. I am working in Microsoft Visual Studio 2017.



In this first case, I am subtracting 2 from the long long variable m in the initialization. This works fine for all n until I try 54, then m will simply not be subtracted by 2.



#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <set>

using namespace std;

#define LL long long

int main()

LL n;
cin >> n;
LL m = pow(2, n + 1) - 2;
cout << m;
return 0;



However, using this code m does get subtracted by 2 and is working as I would expect.



#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <set>

using namespace std;

#define LL long long

int main()

LL n;
cin >> n;
LL m = pow(2, n + 1);
m -= 2;
cout << m;
return 0;



I expect both codes to be equivalent, why is this not the case?







c++ long-long






share|improve this question









New contributor



Edvin K is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.










share|improve this question









New contributor



Edvin K is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








share|improve this question




share|improve this question








edited 2 days ago









vaxquis

7,90354058




7,90354058






New contributor



Edvin K is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








asked May 3 at 13:42









Edvin KEdvin K

914




914




New contributor



Edvin K is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




New contributor




Edvin K is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









  • 24





    I'm curious where you picked up #define LL long long. I see it pretty often on this site, but I'm not aware of who or what is propagating it. Edit : Is it another one of those code golf habits?

    – François Andrieux
    May 3 at 13:54







  • 12





    using namespace std; is considered bad practice.

    – L. F.
    May 3 at 13:55






  • 22





    @Lucas but using LL = long long is also compile time, same size to type, and better. There is no reason to use a macro there

    – Guillaume Racicot
    May 3 at 14:04







  • 20





    @pipe: We understand perfectly well why. We don't want to promote bad practices just because you think it's "magically fine" for code examples. There are plenty of code examples on this site that were broken by using namespace std;

    – Mooing Duck
    May 3 at 16:56






  • 10





    @ThomasMatthews when you're telling people to prefer bit-shift for signed integer types, please alert them that for signed integer types overflow is undefined behavior, that this is not just theoretical undefined behavior but can create actual bugs on common compilers like gcc, and that the numerical result can be surprising and unexpected if you don't consciously think about overflow even when it is compiled to behave exactly as expected for a fixed-width integer type.

    – mtraceur
    May 3 at 21:13












  • 24





    I'm curious where you picked up #define LL long long. I see it pretty often on this site, but I'm not aware of who or what is propagating it. Edit : Is it another one of those code golf habits?

    – François Andrieux
    May 3 at 13:54







  • 12





    using namespace std; is considered bad practice.

    – L. F.
    May 3 at 13:55






  • 22





    @Lucas but using LL = long long is also compile time, same size to type, and better. There is no reason to use a macro there

    – Guillaume Racicot
    May 3 at 14:04







  • 20





    @pipe: We understand perfectly well why. We don't want to promote bad practices just because you think it's "magically fine" for code examples. There are plenty of code examples on this site that were broken by using namespace std;

    – Mooing Duck
    May 3 at 16:56






  • 10





    @ThomasMatthews when you're telling people to prefer bit-shift for signed integer types, please alert them that for signed integer types overflow is undefined behavior, that this is not just theoretical undefined behavior but can create actual bugs on common compilers like gcc, and that the numerical result can be surprising and unexpected if you don't consciously think about overflow even when it is compiled to behave exactly as expected for a fixed-width integer type.

    – mtraceur
    May 3 at 21:13







24




24





I'm curious where you picked up #define LL long long. I see it pretty often on this site, but I'm not aware of who or what is propagating it. Edit : Is it another one of those code golf habits?

– François Andrieux
May 3 at 13:54






I'm curious where you picked up #define LL long long. I see it pretty often on this site, but I'm not aware of who or what is propagating it. Edit : Is it another one of those code golf habits?

– François Andrieux
May 3 at 13:54





12




12





using namespace std; is considered bad practice.

– L. F.
May 3 at 13:55





using namespace std; is considered bad practice.

– L. F.
May 3 at 13:55




22




22





@Lucas but using LL = long long is also compile time, same size to type, and better. There is no reason to use a macro there

– Guillaume Racicot
May 3 at 14:04






@Lucas but using LL = long long is also compile time, same size to type, and better. There is no reason to use a macro there

– Guillaume Racicot
May 3 at 14:04





20




20





@pipe: We understand perfectly well why. We don't want to promote bad practices just because you think it's "magically fine" for code examples. There are plenty of code examples on this site that were broken by using namespace std;

– Mooing Duck
May 3 at 16:56





@pipe: We understand perfectly well why. We don't want to promote bad practices just because you think it's "magically fine" for code examples. There are plenty of code examples on this site that were broken by using namespace std;

– Mooing Duck
May 3 at 16:56




10




10





@ThomasMatthews when you're telling people to prefer bit-shift for signed integer types, please alert them that for signed integer types overflow is undefined behavior, that this is not just theoretical undefined behavior but can create actual bugs on common compilers like gcc, and that the numerical result can be surprising and unexpected if you don't consciously think about overflow even when it is compiled to behave exactly as expected for a fixed-width integer type.

– mtraceur
May 3 at 21:13





@ThomasMatthews when you're telling people to prefer bit-shift for signed integer types, please alert them that for signed integer types overflow is undefined behavior, that this is not just theoretical undefined behavior but can create actual bugs on common compilers like gcc, and that the numerical result can be surprising and unexpected if you don't consciously think about overflow even when it is compiled to behave exactly as expected for a fixed-width integer type.

– mtraceur
May 3 at 21:13












3 Answers
3






active

oldest

votes


















39














The issue with



LL m = pow(2, n + 1) - 2;


is that pow(2, n + 1) is not a long long. It has the type double and because the value is so large, subtracting 2 from it will not change its value. That means that m will not have the correct value. As you have already found, you need to assign the result first and then do the subtraction. Another alternative is to write your own pow that will return a integer type when given an integer type so you can do the raising to the power and subtraction at the same time.






share|improve this answer




















  • 8





    For the OP: You should use bit shifting instead of pow() function. Something like (1 << (n + 1)).

    – Thomas Matthews
    May 3 at 14:17






  • 1





    @StackDanny The problem is at pow(2, 54), not pow(2, 53)

    – NathanOliver
    May 3 at 14:24






  • 5





    Good answer but you should probably mention that the reason it works in the second example is that pow(2,n) "accidentally" fits exactly in the most commonly used floating point representation, even for very large results, so there is never a round-off error involved.

    – pipe
    May 3 at 14:55






  • 2





    @pipe, for powers of two and binary computers, it's not an "accident" in any way.

    – ilkkachu
    May 3 at 18:32







  • 2





    @ThomasMatthews you'll need 1ULL << (n + 1) to shift more than 31 bits

    – phuclv
    2 days ago


















13















I expect both codes to be equivalent, why is this not the case?




Your expectation is wrong. Your second code would be equivalent to this:



auto m = static_cast<LL>( pow(2, n + 1) ) - 2;


as due to conversion rule for arithmetic operators and the fact that std::pow() returns double in this case:




For the binary operators (except shifts), if the promoted operands have different types, additional set of implicit conversions is applied, known as usual arithmetic conversions with the goal to produce the common type (also accessible via the std::common_type type trait). If, prior to any integral promotion, one operand is of enumeration type and the other operand is of a floating-point type or a different enumeration type, this behavior is deprecated. (since C++20)



If either operand has scoped enumeration type, no conversion is performed: the other operand and the return type must have the same type



Otherwise, if either operand is long double, the other operand is converted to long double



Otherwise, if either operand is double, the other operand is converted to double



Otherwise, if either operand is float, the other operand is converted to float



...




(emphasis is mine) your original expression would lead to double - double instead of long long int - long long int as you do in the second case hence the difference.






share|improve this answer
































    11














    The pow function returns a value of type double, which only has 53 bits of precision. While the returned value will fit in a double even if n is greater than 53, subtracting 2 results in a value of type double that requires more than 53 bits of precision so the result of the subtraction is rounded to the nearest representable value.



    The reason breaking out the subtraction works is because the double value returned from pow is assigned to a long long, then you subtract an int from a long long.



    Since you're not dealing with floating point numbers and you're only raising 2 to a power, you can replace the call to pow with a simple left shift:



    LL m = (1LL << (n + 1)) - 2;


    This keeps all intermediate values at type long long.






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



      );






      Edvin K is a new contributor. Be nice, and check out our Code of Conduct.









      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55971072%2fwhy-is-my-arithmetic-with-a-long-long-int-behaving-this-way%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      39














      The issue with



      LL m = pow(2, n + 1) - 2;


      is that pow(2, n + 1) is not a long long. It has the type double and because the value is so large, subtracting 2 from it will not change its value. That means that m will not have the correct value. As you have already found, you need to assign the result first and then do the subtraction. Another alternative is to write your own pow that will return a integer type when given an integer type so you can do the raising to the power and subtraction at the same time.






      share|improve this answer




















      • 8





        For the OP: You should use bit shifting instead of pow() function. Something like (1 << (n + 1)).

        – Thomas Matthews
        May 3 at 14:17






      • 1





        @StackDanny The problem is at pow(2, 54), not pow(2, 53)

        – NathanOliver
        May 3 at 14:24






      • 5





        Good answer but you should probably mention that the reason it works in the second example is that pow(2,n) "accidentally" fits exactly in the most commonly used floating point representation, even for very large results, so there is never a round-off error involved.

        – pipe
        May 3 at 14:55






      • 2





        @pipe, for powers of two and binary computers, it's not an "accident" in any way.

        – ilkkachu
        May 3 at 18:32







      • 2





        @ThomasMatthews you'll need 1ULL << (n + 1) to shift more than 31 bits

        – phuclv
        2 days ago















      39














      The issue with



      LL m = pow(2, n + 1) - 2;


      is that pow(2, n + 1) is not a long long. It has the type double and because the value is so large, subtracting 2 from it will not change its value. That means that m will not have the correct value. As you have already found, you need to assign the result first and then do the subtraction. Another alternative is to write your own pow that will return a integer type when given an integer type so you can do the raising to the power and subtraction at the same time.






      share|improve this answer




















      • 8





        For the OP: You should use bit shifting instead of pow() function. Something like (1 << (n + 1)).

        – Thomas Matthews
        May 3 at 14:17






      • 1





        @StackDanny The problem is at pow(2, 54), not pow(2, 53)

        – NathanOliver
        May 3 at 14:24






      • 5





        Good answer but you should probably mention that the reason it works in the second example is that pow(2,n) "accidentally" fits exactly in the most commonly used floating point representation, even for very large results, so there is never a round-off error involved.

        – pipe
        May 3 at 14:55






      • 2





        @pipe, for powers of two and binary computers, it's not an "accident" in any way.

        – ilkkachu
        May 3 at 18:32







      • 2





        @ThomasMatthews you'll need 1ULL << (n + 1) to shift more than 31 bits

        – phuclv
        2 days ago













      39












      39








      39







      The issue with



      LL m = pow(2, n + 1) - 2;


      is that pow(2, n + 1) is not a long long. It has the type double and because the value is so large, subtracting 2 from it will not change its value. That means that m will not have the correct value. As you have already found, you need to assign the result first and then do the subtraction. Another alternative is to write your own pow that will return a integer type when given an integer type so you can do the raising to the power and subtraction at the same time.






      share|improve this answer















      The issue with



      LL m = pow(2, n + 1) - 2;


      is that pow(2, n + 1) is not a long long. It has the type double and because the value is so large, subtracting 2 from it will not change its value. That means that m will not have the correct value. As you have already found, you need to assign the result first and then do the subtraction. Another alternative is to write your own pow that will return a integer type when given an integer type so you can do the raising to the power and subtraction at the same time.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited May 3 at 14:48









      Medinoc

      5,9291230




      5,9291230










      answered May 3 at 13:47









      NathanOliverNathanOliver

      101k17142225




      101k17142225







      • 8





        For the OP: You should use bit shifting instead of pow() function. Something like (1 << (n + 1)).

        – Thomas Matthews
        May 3 at 14:17






      • 1





        @StackDanny The problem is at pow(2, 54), not pow(2, 53)

        – NathanOliver
        May 3 at 14:24






      • 5





        Good answer but you should probably mention that the reason it works in the second example is that pow(2,n) "accidentally" fits exactly in the most commonly used floating point representation, even for very large results, so there is never a round-off error involved.

        – pipe
        May 3 at 14:55






      • 2





        @pipe, for powers of two and binary computers, it's not an "accident" in any way.

        – ilkkachu
        May 3 at 18:32







      • 2





        @ThomasMatthews you'll need 1ULL << (n + 1) to shift more than 31 bits

        – phuclv
        2 days ago












      • 8





        For the OP: You should use bit shifting instead of pow() function. Something like (1 << (n + 1)).

        – Thomas Matthews
        May 3 at 14:17






      • 1





        @StackDanny The problem is at pow(2, 54), not pow(2, 53)

        – NathanOliver
        May 3 at 14:24






      • 5





        Good answer but you should probably mention that the reason it works in the second example is that pow(2,n) "accidentally" fits exactly in the most commonly used floating point representation, even for very large results, so there is never a round-off error involved.

        – pipe
        May 3 at 14:55






      • 2





        @pipe, for powers of two and binary computers, it's not an "accident" in any way.

        – ilkkachu
        May 3 at 18:32







      • 2





        @ThomasMatthews you'll need 1ULL << (n + 1) to shift more than 31 bits

        – phuclv
        2 days ago







      8




      8





      For the OP: You should use bit shifting instead of pow() function. Something like (1 << (n + 1)).

      – Thomas Matthews
      May 3 at 14:17





      For the OP: You should use bit shifting instead of pow() function. Something like (1 << (n + 1)).

      – Thomas Matthews
      May 3 at 14:17




      1




      1





      @StackDanny The problem is at pow(2, 54), not pow(2, 53)

      – NathanOliver
      May 3 at 14:24





      @StackDanny The problem is at pow(2, 54), not pow(2, 53)

      – NathanOliver
      May 3 at 14:24




      5




      5





      Good answer but you should probably mention that the reason it works in the second example is that pow(2,n) "accidentally" fits exactly in the most commonly used floating point representation, even for very large results, so there is never a round-off error involved.

      – pipe
      May 3 at 14:55





      Good answer but you should probably mention that the reason it works in the second example is that pow(2,n) "accidentally" fits exactly in the most commonly used floating point representation, even for very large results, so there is never a round-off error involved.

      – pipe
      May 3 at 14:55




      2




      2





      @pipe, for powers of two and binary computers, it's not an "accident" in any way.

      – ilkkachu
      May 3 at 18:32






      @pipe, for powers of two and binary computers, it's not an "accident" in any way.

      – ilkkachu
      May 3 at 18:32





      2




      2





      @ThomasMatthews you'll need 1ULL << (n + 1) to shift more than 31 bits

      – phuclv
      2 days ago





      @ThomasMatthews you'll need 1ULL << (n + 1) to shift more than 31 bits

      – phuclv
      2 days ago













      13















      I expect both codes to be equivalent, why is this not the case?




      Your expectation is wrong. Your second code would be equivalent to this:



      auto m = static_cast<LL>( pow(2, n + 1) ) - 2;


      as due to conversion rule for arithmetic operators and the fact that std::pow() returns double in this case:




      For the binary operators (except shifts), if the promoted operands have different types, additional set of implicit conversions is applied, known as usual arithmetic conversions with the goal to produce the common type (also accessible via the std::common_type type trait). If, prior to any integral promotion, one operand is of enumeration type and the other operand is of a floating-point type or a different enumeration type, this behavior is deprecated. (since C++20)



      If either operand has scoped enumeration type, no conversion is performed: the other operand and the return type must have the same type



      Otherwise, if either operand is long double, the other operand is converted to long double



      Otherwise, if either operand is double, the other operand is converted to double



      Otherwise, if either operand is float, the other operand is converted to float



      ...




      (emphasis is mine) your original expression would lead to double - double instead of long long int - long long int as you do in the second case hence the difference.






      share|improve this answer





























        13















        I expect both codes to be equivalent, why is this not the case?




        Your expectation is wrong. Your second code would be equivalent to this:



        auto m = static_cast<LL>( pow(2, n + 1) ) - 2;


        as due to conversion rule for arithmetic operators and the fact that std::pow() returns double in this case:




        For the binary operators (except shifts), if the promoted operands have different types, additional set of implicit conversions is applied, known as usual arithmetic conversions with the goal to produce the common type (also accessible via the std::common_type type trait). If, prior to any integral promotion, one operand is of enumeration type and the other operand is of a floating-point type or a different enumeration type, this behavior is deprecated. (since C++20)



        If either operand has scoped enumeration type, no conversion is performed: the other operand and the return type must have the same type



        Otherwise, if either operand is long double, the other operand is converted to long double



        Otherwise, if either operand is double, the other operand is converted to double



        Otherwise, if either operand is float, the other operand is converted to float



        ...




        (emphasis is mine) your original expression would lead to double - double instead of long long int - long long int as you do in the second case hence the difference.






        share|improve this answer



























          13












          13








          13








          I expect both codes to be equivalent, why is this not the case?




          Your expectation is wrong. Your second code would be equivalent to this:



          auto m = static_cast<LL>( pow(2, n + 1) ) - 2;


          as due to conversion rule for arithmetic operators and the fact that std::pow() returns double in this case:




          For the binary operators (except shifts), if the promoted operands have different types, additional set of implicit conversions is applied, known as usual arithmetic conversions with the goal to produce the common type (also accessible via the std::common_type type trait). If, prior to any integral promotion, one operand is of enumeration type and the other operand is of a floating-point type or a different enumeration type, this behavior is deprecated. (since C++20)



          If either operand has scoped enumeration type, no conversion is performed: the other operand and the return type must have the same type



          Otherwise, if either operand is long double, the other operand is converted to long double



          Otherwise, if either operand is double, the other operand is converted to double



          Otherwise, if either operand is float, the other operand is converted to float



          ...




          (emphasis is mine) your original expression would lead to double - double instead of long long int - long long int as you do in the second case hence the difference.






          share|improve this answer
















          I expect both codes to be equivalent, why is this not the case?




          Your expectation is wrong. Your second code would be equivalent to this:



          auto m = static_cast<LL>( pow(2, n + 1) ) - 2;


          as due to conversion rule for arithmetic operators and the fact that std::pow() returns double in this case:




          For the binary operators (except shifts), if the promoted operands have different types, additional set of implicit conversions is applied, known as usual arithmetic conversions with the goal to produce the common type (also accessible via the std::common_type type trait). If, prior to any integral promotion, one operand is of enumeration type and the other operand is of a floating-point type or a different enumeration type, this behavior is deprecated. (since C++20)



          If either operand has scoped enumeration type, no conversion is performed: the other operand and the return type must have the same type



          Otherwise, if either operand is long double, the other operand is converted to long double



          Otherwise, if either operand is double, the other operand is converted to double



          Otherwise, if either operand is float, the other operand is converted to float



          ...




          (emphasis is mine) your original expression would lead to double - double instead of long long int - long long int as you do in the second case hence the difference.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited May 3 at 14:26

























          answered May 3 at 14:17









          SlavaSlava

          33.4k12968




          33.4k12968





















              11














              The pow function returns a value of type double, which only has 53 bits of precision. While the returned value will fit in a double even if n is greater than 53, subtracting 2 results in a value of type double that requires more than 53 bits of precision so the result of the subtraction is rounded to the nearest representable value.



              The reason breaking out the subtraction works is because the double value returned from pow is assigned to a long long, then you subtract an int from a long long.



              Since you're not dealing with floating point numbers and you're only raising 2 to a power, you can replace the call to pow with a simple left shift:



              LL m = (1LL << (n + 1)) - 2;


              This keeps all intermediate values at type long long.






              share|improve this answer



























                11














                The pow function returns a value of type double, which only has 53 bits of precision. While the returned value will fit in a double even if n is greater than 53, subtracting 2 results in a value of type double that requires more than 53 bits of precision so the result of the subtraction is rounded to the nearest representable value.



                The reason breaking out the subtraction works is because the double value returned from pow is assigned to a long long, then you subtract an int from a long long.



                Since you're not dealing with floating point numbers and you're only raising 2 to a power, you can replace the call to pow with a simple left shift:



                LL m = (1LL << (n + 1)) - 2;


                This keeps all intermediate values at type long long.






                share|improve this answer

























                  11












                  11








                  11







                  The pow function returns a value of type double, which only has 53 bits of precision. While the returned value will fit in a double even if n is greater than 53, subtracting 2 results in a value of type double that requires more than 53 bits of precision so the result of the subtraction is rounded to the nearest representable value.



                  The reason breaking out the subtraction works is because the double value returned from pow is assigned to a long long, then you subtract an int from a long long.



                  Since you're not dealing with floating point numbers and you're only raising 2 to a power, you can replace the call to pow with a simple left shift:



                  LL m = (1LL << (n + 1)) - 2;


                  This keeps all intermediate values at type long long.






                  share|improve this answer













                  The pow function returns a value of type double, which only has 53 bits of precision. While the returned value will fit in a double even if n is greater than 53, subtracting 2 results in a value of type double that requires more than 53 bits of precision so the result of the subtraction is rounded to the nearest representable value.



                  The reason breaking out the subtraction works is because the double value returned from pow is assigned to a long long, then you subtract an int from a long long.



                  Since you're not dealing with floating point numbers and you're only raising 2 to a power, you can replace the call to pow with a simple left shift:



                  LL m = (1LL << (n + 1)) - 2;


                  This keeps all intermediate values at type long long.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered May 3 at 15:33









                  dbushdbush

                  106k15111150




                  106k15111150




















                      Edvin K is a new contributor. Be nice, and check out our Code of Conduct.









                      draft saved

                      draft discarded


















                      Edvin K is a new contributor. Be nice, and check out our Code of Conduct.












                      Edvin K is a new contributor. Be nice, and check out our Code of Conduct.











                      Edvin K is a new contributor. Be nice, and check out our Code of Conduct.














                      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%2f55971072%2fwhy-is-my-arithmetic-with-a-long-long-int-behaving-this-way%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

                      Grendel Contents Story Scholarship Depictions Notes References Navigation menu10.1093/notesj/gjn112Berserkeree

                      Area configuration aggregation error after install Porto themeMagento 2.1 CE Installed but front/backend not loading/workingCSS not loading on page within Magento 2 pageCannot install module in Magento 2no commands defined in the “setup” namespace. in Magento2Magento 2: Static files are present but shows 404Why do i have to always run the commands to clean cache in Magento 2.1.8?Failure reason: 'Unable to unserialize value.'Error 500 after magento migrationIn production mode the site does not loadMagento 2 : Error 500 after installing

                      Middle Expansion Olielle Resaix Definition: Uttering songs of triumph shouting with joy triumphant exulting Sejunction Journal 붙다 달 고급 품목 외출 The stretch trades the screeching tin. Definition: The act of speaking with a drawl a drawl Cough Sand Definition: An uproar a quarrel a noisy outbreak Shake Iron Publicize Horse House Baby 사과 Resaix Flaggy Jelly Temporary Unequaled Puppet A drop in the bucket Shrew 성격 회원 성질 미팅 The burn frames the tacky quality. Materialistic The smoke reduces the way. Yammoe Nondescript Cheek 얼굴 배 약하다 날리다 타다 The illegal country shows the iron. Help Rule Drearien Smoke Teaching Meaty Wasp Abraham Lincoln Jaws 진심 수리하다 Size Cork Idea Convert Think Lark John Lennon 거울 청소 군 추천하다 아이스크림