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?How do I parse a string to a float or int in Python?Why can templates only be implemented in the header file?What is the difference between const int*, const int * const, and int const *?Why is “using namespace std” considered bad practice?Why not use Double or Float to represent currency?Easiest way to convert int to string in C++Why doesn't GCC optimize a*a*a*a*a*a to (a*a*a)*(a*a*a)?Why are elementwise additions much faster in separate loops than in a combined loop?Why does changing 0.1f to 0 slow down performance by 10x?Why is it faster to process a sorted array than an unsorted array?

the grammar about `adv adv` as 'too quickly'

Why are BJTs common in output stages of power amplifiers?

Why do the lights go out when someone enters the dining room on this ship?

Did galley captains put corks in the mouths of slave rowers to keep them quiet?

Acronyms in HDD specification

What dog breeds survive the apocalypse for generations?

Can only the master initiate communication in SPI whereas in I2C the slave can also initiate the communication?

Will a coyote attack my dog on a leash while I'm on a hiking trail?

Find the unknown area, x

Is there an academic word that means "to split hairs over"?

Developers demotivated due to working on same project for more than 2 years

Do Grothendieck universes matter for an algebraic geometer?

Is it safe to use two single-pole breakers for a 240 V circuit?

Why didn't the Avengers use this object earlier?

How might a landlocked lake become a complete ecosystem?

"The van's really booking"

Unexpected Netflix account registered to my Gmail address - any way it could be a hack attempt?

Is 95% of what you read in the financial press “either wrong or irrelevant?”

How can we allow remote players to effectively interact with a physical tabletop battle-map?

How can I add a .pem private key fingerprint entry to known_hosts before connecting with ssh?

How to describe a building set which is like LEGO without using the "LEGO" word?

Filter a data-frame and add a new column according to the given condition

How can a layman easily get the consensus view of what academia *thinks* about a subject?

Why did the soldiers of the North disobey Jon?



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?How do I parse a string to a float or int in Python?Why can templates only be implemented in the header file?What is the difference between const int*, const int * const, and int const *?Why is “using namespace std” considered bad practice?Why not use Double or Float to represent currency?Easiest way to convert int to string in C++Why doesn't GCC optimize a*a*a*a*a*a to (a*a*a)*(a*a*a)?Why are elementwise additions much faster in separate loops than in a combined loop?Why does changing 0.1f to 0 slow down performance by 10x?Why is it faster to process a sorted array than an unsorted array?






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








26















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



















  • 25





    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







  • 21





    @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

















26















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



















  • 25





    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







  • 21





    @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













26












26








26


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
















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++ floating-point precision long-long






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 10 at 23:07









oldherl

179211




179211










asked May 3 at 13:42









Edvin KEdvin K

13925




13925







  • 25





    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







  • 21





    @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












  • 25





    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







  • 21





    @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







25




25





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





21




21





@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


















46














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




















  • 10





    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
    May 4 at 4:25


















17















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
































    15














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



      );













      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









      46














      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




















      • 10





        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
        May 4 at 4:25















      46














      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




















      • 10





        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
        May 4 at 4:25













      46












      46








      46







      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

      102k17145227




      102k17145227







      • 10





        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
        May 4 at 4:25












      • 10





        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
        May 4 at 4:25







      10




      10





      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
      May 4 at 4:25





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

      – phuclv
      May 4 at 4:25













      17















      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





























        17















        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



























          17












          17








          17








          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





















              15














              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



























                15














                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

























                  15












                  15








                  15







                  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

                  106k15111151




                  106k15111151



























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

                      Wikipedia:Vital articles Мазмуну Biography - Өмүр баян Philosophy and psychology - Философия жана психология Religion - Дин Social sciences - Коомдук илимдер Language and literature - Тил жана адабият Science - Илим Technology - Технология Arts and recreation - Искусство жана эс алуу History and geography - Тарых жана география Навигация менюсу

                      Bruxelas-Capital Índice Historia | Composición | Situación lingüística | Clima | Cidades irmandadas | Notas | Véxase tamén | Menú de navegacióneO uso das linguas en Bruxelas e a situación do neerlandés"Rexión de Bruxelas Capital"o orixinalSitio da rexiónPáxina de Bruselas no sitio da Oficina de Promoción Turística de Valonia e BruxelasMapa Interactivo da Rexión de Bruxelas-CapitaleeWorldCat332144929079854441105155190212ID28008674080552-90000 0001 0666 3698n94104302ID540940339365017018237

                      What should I write in an apology letter, since I have decided not to join a company after accepting an offer letterShould I keep looking after accepting a job offer?What should I do when I've been verbally told I would get an offer letter, but still haven't gotten one after 4 weeks?Do I accept an offer from a company that I am not likely to join?New job hasn't confirmed starting date and I want to give current employer as much notice as possibleHow should I address my manager in my resignation letter?HR delayed background verification, now jobless as resignedNo email communication after accepting a formal written offer. How should I phrase the call?What should I do if after receiving a verbal offer letter I am informed that my written job offer is put on hold due to some internal issues?Should I inform the current employer that I am about to resign within 1-2 weeks since I have signed the offer letter and waiting for visa?What company will do, if I send their offer letter to another company