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

                      Club Baloncesto Breogán Índice Historia | Pavillón | Nome | O Breogán na cultura popular | Xogadores | Adestradores | Presidentes | Palmarés | Historial | Líderes | Notas | Véxase tamén | Menú de navegacióncbbreogan.galCadroGuía oficial da ACB 2009-10, páxina 201Guía oficial ACB 1992, páxina 183. Editorial DB.É de 6.500 espectadores sentados axeitándose á última normativa"Estudiantes Junior, entre as mellores canteiras"o orixinalHemeroteca El Mundo Deportivo, 16 setembro de 1970, páxina 12Historia do BreogánAlfredo Pérez, o último canoneiroHistoria C.B. BreogánHemeroteca de El Mundo DeportivoJimmy Wright, norteamericano do Breogán deixará Lugo por ameazas de morteResultados de Breogán en 1986-87Resultados de Breogán en 1990-91Ficha de Velimir Perasović en acb.comResultados de Breogán en 1994-95Breogán arrasa al Barça. "El Mundo Deportivo", 27 de setembro de 1999, páxina 58CB Breogán - FC BarcelonaA FEB invita a participar nunha nova Liga EuropeaCharlie Bell na prensa estatalMáximos anotadores 2005Tempada 2005-06 : Tódolos Xogadores da Xornada""Non quero pensar nunha man negra, mais pregúntome que está a pasar""o orixinalRaúl López, orgulloso dos xogadores, presume da boa saúde económica do BreogánJulio González confirma que cesa como presidente del BreogánHomenaxe a Lisardo GómezA tempada do rexurdimento celesteEntrevista a Lisardo GómezEl COB dinamita el Pazo para forzar el quinto (69-73)Cafés Candelas, patrocinador del CB Breogán"Suso Lázare, novo presidente do Breogán"o orixinalCafés Candelas Breogán firma el mayor triunfo de la historiaEl Breogán realizará 17 homenajes por su cincuenta aniversario"O Breogán honra ao seu fundador e primeiro presidente"o orixinalMiguel Giao recibiu a homenaxe do PazoHomenaxe aos primeiros gladiadores celestesO home que nos amosa como ver o Breo co corazónTita Franco será homenaxeada polos #50anosdeBreoJulio Vila recibirá unha homenaxe in memoriam polos #50anosdeBreo"O Breogán homenaxeará aos seus aboados máis veteráns"Pechada ovación a «Capi» Sanmartín e Ricardo «Corazón de González»Homenaxe por décadas de informaciónPaco García volve ao Pazo con motivo do 50 aniversario"Resultados y clasificaciones""O Cafés Candelas Breogán, campión da Copa Princesa""O Cafés Candelas Breogán, equipo ACB"C.B. Breogán"Proxecto social"o orixinal"Centros asociados"o orixinalFicha en imdb.comMario Camus trata la recuperación del amor en 'La vieja música', su última película"Páxina web oficial""Club Baloncesto Breogán""C. B. Breogán S.A.D."eehttp://www.fegaba.com

                      Vilaño, A Laracha Índice Patrimonio | Lugares e parroquias | Véxase tamén | Menú de navegación43°14′52″N 8°36′03″O / 43.24775, -8.60070

                      Cegueira Índice Epidemioloxía | Deficiencia visual | Tipos de cegueira | Principais causas de cegueira | Tratamento | Técnicas de adaptación e axudas | Vida dos cegos | Primeiros auxilios | Crenzas respecto das persoas cegas | Crenzas das persoas cegas | O neno deficiente visual | Aspectos psicolóxicos da cegueira | Notas | Véxase tamén | Menú de navegación54.054.154.436928256blindnessDicionario da Real Academia GalegaPortal das Palabras"International Standards: Visual Standards — Aspects and Ranges of Vision Loss with Emphasis on Population Surveys.""Visual impairment and blindness""Presentan un plan para previr a cegueira"o orixinalACCDV Associació Catalana de Cecs i Disminuïts Visuals - PMFTrachoma"Effect of gene therapy on visual function in Leber's congenital amaurosis"1844137110.1056/NEJMoa0802268Cans guía - os mellores amigos dos cegosArquivadoEscola de cans guía para cegos en Mortágua, PortugalArquivado"Tecnología para ciegos y deficientes visuales. Recopilación de recursos gratuitos en la Red""Colorino""‘COL.diesis’, escuchar los sonidos del color""COL.diesis: Transforming Colour into Melody and Implementing the Result in a Colour Sensor Device"o orixinal"Sistema de desarrollo de sinestesia color-sonido para invidentes utilizando un protocolo de audio""Enseñanza táctil - geometría y color. Juegos didácticos para niños ciegos y videntes""Sistema Constanz"L'ocupació laboral dels cecs a l'Estat espanyol està pràcticament equiparada a la de les persones amb visió, entrevista amb Pedro ZuritaONCE (Organización Nacional de Cegos de España)Prevención da cegueiraDescrición de deficiencias visuais (Disc@pnet)Braillín, un boneco atractivo para calquera neno, con ou sen discapacidade, que permite familiarizarse co sistema de escritura e lectura brailleAxudas Técnicas36838ID00897494007150-90057129528256DOID:1432HP:0000618D001766C10.597.751.941.162C97109C0155020