Converting a negative decimal into binary in C





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







0















I'm currently working on a program that (among others) has to convert a decimal number into binary, octal & hexadecimal.
This already works with this code:



    int e = 0;
}
while(i != 0){
str[e] = (i%b) + '0';
i = i / b;
if(str[e] > '9'){
str[e] = str[e] + 7;
}
e++;

}
if(vorzeichen == -1){
str[e] = '1';
e++;
}
if(b == 16){
str[e] = 'x';
str[e+1] = '0';
}
else if(b == 8){
str[e] = '0';
}
}


b is the base (2 for binary, 8 for octal & 16 for hexa) and i is the number that i want to convert.
This gives out a string of characters which i then reverse to get the correct number. Now if i try this with negative numbers, it gives out strings not only containing 0 and 1 but also /, which is '0' -1 on the ASCII table. For octal and decimal it also gives out characters below the '/' on the ASCII table. I've attempted different possible solutions but none seemed to give the desired result. What I read on the internet is that I have to use the 2s Complement I'm stuck trying to use it. It just doesn't seem to work for me.










share|improve this question























  • snprintf(str, size_of_str, "%o", integer_value)? Replace "%o" with "%x" for hexadecimal. For binary I would recommend using bitwise operations like shifting and AND.

    – Some programmer dude
    Nov 23 '18 at 11:52













  • I can't use library functions

    – Halsi
    Nov 23 '18 at 11:55











  • Then I suggest you take some time to learn how to debug your code.

    – Some programmer dude
    Nov 23 '18 at 11:59











  • This is the sort of situation where I suggest writing the algorithm on paper first and see how it behaves for different inputs. Once you have something solid going, it's easy to write it in code. Take your time to learn.

    – luci88filter
    Nov 23 '18 at 12:11


















0















I'm currently working on a program that (among others) has to convert a decimal number into binary, octal & hexadecimal.
This already works with this code:



    int e = 0;
}
while(i != 0){
str[e] = (i%b) + '0';
i = i / b;
if(str[e] > '9'){
str[e] = str[e] + 7;
}
e++;

}
if(vorzeichen == -1){
str[e] = '1';
e++;
}
if(b == 16){
str[e] = 'x';
str[e+1] = '0';
}
else if(b == 8){
str[e] = '0';
}
}


b is the base (2 for binary, 8 for octal & 16 for hexa) and i is the number that i want to convert.
This gives out a string of characters which i then reverse to get the correct number. Now if i try this with negative numbers, it gives out strings not only containing 0 and 1 but also /, which is '0' -1 on the ASCII table. For octal and decimal it also gives out characters below the '/' on the ASCII table. I've attempted different possible solutions but none seemed to give the desired result. What I read on the internet is that I have to use the 2s Complement I'm stuck trying to use it. It just doesn't seem to work for me.










share|improve this question























  • snprintf(str, size_of_str, "%o", integer_value)? Replace "%o" with "%x" for hexadecimal. For binary I would recommend using bitwise operations like shifting and AND.

    – Some programmer dude
    Nov 23 '18 at 11:52













  • I can't use library functions

    – Halsi
    Nov 23 '18 at 11:55











  • Then I suggest you take some time to learn how to debug your code.

    – Some programmer dude
    Nov 23 '18 at 11:59











  • This is the sort of situation where I suggest writing the algorithm on paper first and see how it behaves for different inputs. Once you have something solid going, it's easy to write it in code. Take your time to learn.

    – luci88filter
    Nov 23 '18 at 12:11














0












0








0








I'm currently working on a program that (among others) has to convert a decimal number into binary, octal & hexadecimal.
This already works with this code:



    int e = 0;
}
while(i != 0){
str[e] = (i%b) + '0';
i = i / b;
if(str[e] > '9'){
str[e] = str[e] + 7;
}
e++;

}
if(vorzeichen == -1){
str[e] = '1';
e++;
}
if(b == 16){
str[e] = 'x';
str[e+1] = '0';
}
else if(b == 8){
str[e] = '0';
}
}


b is the base (2 for binary, 8 for octal & 16 for hexa) and i is the number that i want to convert.
This gives out a string of characters which i then reverse to get the correct number. Now if i try this with negative numbers, it gives out strings not only containing 0 and 1 but also /, which is '0' -1 on the ASCII table. For octal and decimal it also gives out characters below the '/' on the ASCII table. I've attempted different possible solutions but none seemed to give the desired result. What I read on the internet is that I have to use the 2s Complement I'm stuck trying to use it. It just doesn't seem to work for me.










share|improve this question














I'm currently working on a program that (among others) has to convert a decimal number into binary, octal & hexadecimal.
This already works with this code:



    int e = 0;
}
while(i != 0){
str[e] = (i%b) + '0';
i = i / b;
if(str[e] > '9'){
str[e] = str[e] + 7;
}
e++;

}
if(vorzeichen == -1){
str[e] = '1';
e++;
}
if(b == 16){
str[e] = 'x';
str[e+1] = '0';
}
else if(b == 8){
str[e] = '0';
}
}


b is the base (2 for binary, 8 for octal & 16 for hexa) and i is the number that i want to convert.
This gives out a string of characters which i then reverse to get the correct number. Now if i try this with negative numbers, it gives out strings not only containing 0 and 1 but also /, which is '0' -1 on the ASCII table. For octal and decimal it also gives out characters below the '/' on the ASCII table. I've attempted different possible solutions but none seemed to give the desired result. What I read on the internet is that I have to use the 2s Complement I'm stuck trying to use it. It just doesn't seem to work for me.







c binary decimal






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 23 '18 at 11:49









HalsiHalsi

214




214













  • snprintf(str, size_of_str, "%o", integer_value)? Replace "%o" with "%x" for hexadecimal. For binary I would recommend using bitwise operations like shifting and AND.

    – Some programmer dude
    Nov 23 '18 at 11:52













  • I can't use library functions

    – Halsi
    Nov 23 '18 at 11:55











  • Then I suggest you take some time to learn how to debug your code.

    – Some programmer dude
    Nov 23 '18 at 11:59











  • This is the sort of situation where I suggest writing the algorithm on paper first and see how it behaves for different inputs. Once you have something solid going, it's easy to write it in code. Take your time to learn.

    – luci88filter
    Nov 23 '18 at 12:11



















  • snprintf(str, size_of_str, "%o", integer_value)? Replace "%o" with "%x" for hexadecimal. For binary I would recommend using bitwise operations like shifting and AND.

    – Some programmer dude
    Nov 23 '18 at 11:52













  • I can't use library functions

    – Halsi
    Nov 23 '18 at 11:55











  • Then I suggest you take some time to learn how to debug your code.

    – Some programmer dude
    Nov 23 '18 at 11:59











  • This is the sort of situation where I suggest writing the algorithm on paper first and see how it behaves for different inputs. Once you have something solid going, it's easy to write it in code. Take your time to learn.

    – luci88filter
    Nov 23 '18 at 12:11

















snprintf(str, size_of_str, "%o", integer_value)? Replace "%o" with "%x" for hexadecimal. For binary I would recommend using bitwise operations like shifting and AND.

– Some programmer dude
Nov 23 '18 at 11:52







snprintf(str, size_of_str, "%o", integer_value)? Replace "%o" with "%x" for hexadecimal. For binary I would recommend using bitwise operations like shifting and AND.

– Some programmer dude
Nov 23 '18 at 11:52















I can't use library functions

– Halsi
Nov 23 '18 at 11:55





I can't use library functions

– Halsi
Nov 23 '18 at 11:55













Then I suggest you take some time to learn how to debug your code.

– Some programmer dude
Nov 23 '18 at 11:59





Then I suggest you take some time to learn how to debug your code.

– Some programmer dude
Nov 23 '18 at 11:59













This is the sort of situation where I suggest writing the algorithm on paper first and see how it behaves for different inputs. Once you have something solid going, it's easy to write it in code. Take your time to learn.

– luci88filter
Nov 23 '18 at 12:11





This is the sort of situation where I suggest writing the algorithm on paper first and see how it behaves for different inputs. Once you have something solid going, it's easy to write it in code. Take your time to learn.

– luci88filter
Nov 23 '18 at 12:11












3 Answers
3






active

oldest

votes


















1














if you want to display a negative decimal you just can convert your int to a unsigned int like this :



unsigned int value = (unsigned int)i;


Now you only have to use value instead of i in your program and it will be fine.
Here's a good explanation of why : Converting negative decimal to binary






share|improve this answer































    1














    When converting between different bases/radixes, always work on unsigned integer types.



    Let's say you have long num you wish to convert. Use an unsigned long u. To represent negative values in two's complement format, you can use



    if (num < 0)
    u = 1 + (~(unsigned long)(-num));
    else
    u = num;


    or even shorter,



    unsigned long  u = (num < 0) ? 1 + (~(unsigned long)(-num)) : num;


    This works on all architectures (except for num == LONG_MIN, in which case the above is technically undefined behaviour), even those that do not use two's complement internally, because we essentially convert the absolute value of num. If num was originally negative, we then do the two's complement to the unsigned value.





    In a comment, chux suggested an alternative form which does not rely on UB for num == LONG_MIN (unless LONG_MAX == ULONG_MAX, which would be horribly odd thing to see):



    unsigned long  u = (num < 0) ? 1 + (~((unsigned long)(-1 - num) + 1)) : num;


    This may look "uglier", but a sane C compiler should be able to optimize either one completely away on architectures with two's complement integers. chux's version avoids undefined behaviour by subtracting the negative num from -1, thus mapping -1 to 0, -2 to 1, and so on, ensuring that all negative values are representable as a nonnegative long. That value is then converted to unsigned long. This gets incremented by one, to account for the earlier -1. This procedure yields the correct negation of num.



    In other words, to obtain the absolute value of a long, you can use



    unsigned long  abs_long(const long  num)
    {
    return (num < 0) ? (unsigned long)(-1 - num) + 1u : (unsigned long)num;
    }





    share|improve this answer


























    • Good approach that does not rely on two's complement internally. Corner oops: "It is UB with 2's complement i == INT_MIN and -num.

      – chux
      Nov 23 '18 at 16:40













    • @chux: I'm sure you mean LONG_MIN, as I'm using long, not int. I'm not sure it is worth avoiding the Undefined Behaviour here, nor how would one do so portably without an even larger integer type. Suggestions?

      – Nominal Animal
      Nov 23 '18 at 16:49











    • Yes LONG_MIN was meant, not INT_MIN. To avoid a larger type, 1 + (~((unsigned long)(-1 - num) + 1)); (correct, but ugly) or other code.

      – chux
      Nov 23 '18 at 17:01











    • @chux: Is there anything in the C standards that says LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0? If not, LONG_MIN is not the only case that needs special care.

      – Nominal Animal
      Nov 23 '18 at 17:05













    • Yes, "LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0" is a consequence of C11 §6.2.6.2 2. On a pedantic note, LONG_MAX == ULONG_MAX is possible yet not have come across such a machine for decades. IMO, OP's goal lacks clarity for a highly portable solution- yet good enough solutions can be had.

      – chux
      Nov 23 '18 at 17:11





















    0














    % is the remainder function, not mod.



    With b==2, i%b returns [-1, 0, 1]. This is not the needed functionality for str[e] = (i%b) + '0'; See ... difference between “mod” and “remainder”



    This is the cause of '/' and "also gives out characters below the '/' ".





    Build up the string from the "right"



    With a 2's complement int, a simple approach is to convert to unsigned and avoid a negative result from %. Since code is using % to extract the least significant digit, walk the buffer from right to left.



    #include <limits.h>

    ...
    unsigned u = i;

    // make a temporary buffer large enough for any string output in binary
    // v------v Size of `u` in "bytes"
    // | | v------v Size of a "byte" - commonly 8
    char my_buff[sizeof u & CHAR_BIT + 1];
    int e = 0;

    // Form a pointer to the end so code assigns the least significant digits on the right
    char *p = &my_buff[sizeof my_buff - 1];

    // Strings are null character terminated
    *p = '';

    // Use a `do` loop to insure at least one pass. Useful when `i==0` --> "0"
    do {
    p--;
    p[e] = "0123456789ABCDEF"[u%b]; // Select desired digit
    u = u / b;
    } while (u);

    // "prepend" characters as desired
    if(b == 16){
    *(--p) = 'x';
    *(--p) = '0';
    }
    else if(b == 8 && i != 0){
    *(--p) = '0';
    }

    strcpy(str, p);





    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%2f53446176%2fconverting-a-negative-decimal-into-binary-in-c%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









      1














      if you want to display a negative decimal you just can convert your int to a unsigned int like this :



      unsigned int value = (unsigned int)i;


      Now you only have to use value instead of i in your program and it will be fine.
      Here's a good explanation of why : Converting negative decimal to binary






      share|improve this answer




























        1














        if you want to display a negative decimal you just can convert your int to a unsigned int like this :



        unsigned int value = (unsigned int)i;


        Now you only have to use value instead of i in your program and it will be fine.
        Here's a good explanation of why : Converting negative decimal to binary






        share|improve this answer


























          1












          1








          1







          if you want to display a negative decimal you just can convert your int to a unsigned int like this :



          unsigned int value = (unsigned int)i;


          Now you only have to use value instead of i in your program and it will be fine.
          Here's a good explanation of why : Converting negative decimal to binary






          share|improve this answer













          if you want to display a negative decimal you just can convert your int to a unsigned int like this :



          unsigned int value = (unsigned int)i;


          Now you only have to use value instead of i in your program and it will be fine.
          Here's a good explanation of why : Converting negative decimal to binary







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 23 '18 at 12:04









          StrikholStrikhol

          365




          365

























              1














              When converting between different bases/radixes, always work on unsigned integer types.



              Let's say you have long num you wish to convert. Use an unsigned long u. To represent negative values in two's complement format, you can use



              if (num < 0)
              u = 1 + (~(unsigned long)(-num));
              else
              u = num;


              or even shorter,



              unsigned long  u = (num < 0) ? 1 + (~(unsigned long)(-num)) : num;


              This works on all architectures (except for num == LONG_MIN, in which case the above is technically undefined behaviour), even those that do not use two's complement internally, because we essentially convert the absolute value of num. If num was originally negative, we then do the two's complement to the unsigned value.





              In a comment, chux suggested an alternative form which does not rely on UB for num == LONG_MIN (unless LONG_MAX == ULONG_MAX, which would be horribly odd thing to see):



              unsigned long  u = (num < 0) ? 1 + (~((unsigned long)(-1 - num) + 1)) : num;


              This may look "uglier", but a sane C compiler should be able to optimize either one completely away on architectures with two's complement integers. chux's version avoids undefined behaviour by subtracting the negative num from -1, thus mapping -1 to 0, -2 to 1, and so on, ensuring that all negative values are representable as a nonnegative long. That value is then converted to unsigned long. This gets incremented by one, to account for the earlier -1. This procedure yields the correct negation of num.



              In other words, to obtain the absolute value of a long, you can use



              unsigned long  abs_long(const long  num)
              {
              return (num < 0) ? (unsigned long)(-1 - num) + 1u : (unsigned long)num;
              }





              share|improve this answer


























              • Good approach that does not rely on two's complement internally. Corner oops: "It is UB with 2's complement i == INT_MIN and -num.

                – chux
                Nov 23 '18 at 16:40













              • @chux: I'm sure you mean LONG_MIN, as I'm using long, not int. I'm not sure it is worth avoiding the Undefined Behaviour here, nor how would one do so portably without an even larger integer type. Suggestions?

                – Nominal Animal
                Nov 23 '18 at 16:49











              • Yes LONG_MIN was meant, not INT_MIN. To avoid a larger type, 1 + (~((unsigned long)(-1 - num) + 1)); (correct, but ugly) or other code.

                – chux
                Nov 23 '18 at 17:01











              • @chux: Is there anything in the C standards that says LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0? If not, LONG_MIN is not the only case that needs special care.

                – Nominal Animal
                Nov 23 '18 at 17:05













              • Yes, "LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0" is a consequence of C11 §6.2.6.2 2. On a pedantic note, LONG_MAX == ULONG_MAX is possible yet not have come across such a machine for decades. IMO, OP's goal lacks clarity for a highly portable solution- yet good enough solutions can be had.

                – chux
                Nov 23 '18 at 17:11


















              1














              When converting between different bases/radixes, always work on unsigned integer types.



              Let's say you have long num you wish to convert. Use an unsigned long u. To represent negative values in two's complement format, you can use



              if (num < 0)
              u = 1 + (~(unsigned long)(-num));
              else
              u = num;


              or even shorter,



              unsigned long  u = (num < 0) ? 1 + (~(unsigned long)(-num)) : num;


              This works on all architectures (except for num == LONG_MIN, in which case the above is technically undefined behaviour), even those that do not use two's complement internally, because we essentially convert the absolute value of num. If num was originally negative, we then do the two's complement to the unsigned value.





              In a comment, chux suggested an alternative form which does not rely on UB for num == LONG_MIN (unless LONG_MAX == ULONG_MAX, which would be horribly odd thing to see):



              unsigned long  u = (num < 0) ? 1 + (~((unsigned long)(-1 - num) + 1)) : num;


              This may look "uglier", but a sane C compiler should be able to optimize either one completely away on architectures with two's complement integers. chux's version avoids undefined behaviour by subtracting the negative num from -1, thus mapping -1 to 0, -2 to 1, and so on, ensuring that all negative values are representable as a nonnegative long. That value is then converted to unsigned long. This gets incremented by one, to account for the earlier -1. This procedure yields the correct negation of num.



              In other words, to obtain the absolute value of a long, you can use



              unsigned long  abs_long(const long  num)
              {
              return (num < 0) ? (unsigned long)(-1 - num) + 1u : (unsigned long)num;
              }





              share|improve this answer


























              • Good approach that does not rely on two's complement internally. Corner oops: "It is UB with 2's complement i == INT_MIN and -num.

                – chux
                Nov 23 '18 at 16:40













              • @chux: I'm sure you mean LONG_MIN, as I'm using long, not int. I'm not sure it is worth avoiding the Undefined Behaviour here, nor how would one do so portably without an even larger integer type. Suggestions?

                – Nominal Animal
                Nov 23 '18 at 16:49











              • Yes LONG_MIN was meant, not INT_MIN. To avoid a larger type, 1 + (~((unsigned long)(-1 - num) + 1)); (correct, but ugly) or other code.

                – chux
                Nov 23 '18 at 17:01











              • @chux: Is there anything in the C standards that says LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0? If not, LONG_MIN is not the only case that needs special care.

                – Nominal Animal
                Nov 23 '18 at 17:05













              • Yes, "LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0" is a consequence of C11 §6.2.6.2 2. On a pedantic note, LONG_MAX == ULONG_MAX is possible yet not have come across such a machine for decades. IMO, OP's goal lacks clarity for a highly portable solution- yet good enough solutions can be had.

                – chux
                Nov 23 '18 at 17:11
















              1












              1








              1







              When converting between different bases/radixes, always work on unsigned integer types.



              Let's say you have long num you wish to convert. Use an unsigned long u. To represent negative values in two's complement format, you can use



              if (num < 0)
              u = 1 + (~(unsigned long)(-num));
              else
              u = num;


              or even shorter,



              unsigned long  u = (num < 0) ? 1 + (~(unsigned long)(-num)) : num;


              This works on all architectures (except for num == LONG_MIN, in which case the above is technically undefined behaviour), even those that do not use two's complement internally, because we essentially convert the absolute value of num. If num was originally negative, we then do the two's complement to the unsigned value.





              In a comment, chux suggested an alternative form which does not rely on UB for num == LONG_MIN (unless LONG_MAX == ULONG_MAX, which would be horribly odd thing to see):



              unsigned long  u = (num < 0) ? 1 + (~((unsigned long)(-1 - num) + 1)) : num;


              This may look "uglier", but a sane C compiler should be able to optimize either one completely away on architectures with two's complement integers. chux's version avoids undefined behaviour by subtracting the negative num from -1, thus mapping -1 to 0, -2 to 1, and so on, ensuring that all negative values are representable as a nonnegative long. That value is then converted to unsigned long. This gets incremented by one, to account for the earlier -1. This procedure yields the correct negation of num.



              In other words, to obtain the absolute value of a long, you can use



              unsigned long  abs_long(const long  num)
              {
              return (num < 0) ? (unsigned long)(-1 - num) + 1u : (unsigned long)num;
              }





              share|improve this answer















              When converting between different bases/radixes, always work on unsigned integer types.



              Let's say you have long num you wish to convert. Use an unsigned long u. To represent negative values in two's complement format, you can use



              if (num < 0)
              u = 1 + (~(unsigned long)(-num));
              else
              u = num;


              or even shorter,



              unsigned long  u = (num < 0) ? 1 + (~(unsigned long)(-num)) : num;


              This works on all architectures (except for num == LONG_MIN, in which case the above is technically undefined behaviour), even those that do not use two's complement internally, because we essentially convert the absolute value of num. If num was originally negative, we then do the two's complement to the unsigned value.





              In a comment, chux suggested an alternative form which does not rely on UB for num == LONG_MIN (unless LONG_MAX == ULONG_MAX, which would be horribly odd thing to see):



              unsigned long  u = (num < 0) ? 1 + (~((unsigned long)(-1 - num) + 1)) : num;


              This may look "uglier", but a sane C compiler should be able to optimize either one completely away on architectures with two's complement integers. chux's version avoids undefined behaviour by subtracting the negative num from -1, thus mapping -1 to 0, -2 to 1, and so on, ensuring that all negative values are representable as a nonnegative long. That value is then converted to unsigned long. This gets incremented by one, to account for the earlier -1. This procedure yields the correct negation of num.



              In other words, to obtain the absolute value of a long, you can use



              unsigned long  abs_long(const long  num)
              {
              return (num < 0) ? (unsigned long)(-1 - num) + 1u : (unsigned long)num;
              }






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Nov 23 '18 at 17:26

























              answered Nov 23 '18 at 12:08









              Nominal AnimalNominal Animal

              30.5k33463




              30.5k33463













              • Good approach that does not rely on two's complement internally. Corner oops: "It is UB with 2's complement i == INT_MIN and -num.

                – chux
                Nov 23 '18 at 16:40













              • @chux: I'm sure you mean LONG_MIN, as I'm using long, not int. I'm not sure it is worth avoiding the Undefined Behaviour here, nor how would one do so portably without an even larger integer type. Suggestions?

                – Nominal Animal
                Nov 23 '18 at 16:49











              • Yes LONG_MIN was meant, not INT_MIN. To avoid a larger type, 1 + (~((unsigned long)(-1 - num) + 1)); (correct, but ugly) or other code.

                – chux
                Nov 23 '18 at 17:01











              • @chux: Is there anything in the C standards that says LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0? If not, LONG_MIN is not the only case that needs special care.

                – Nominal Animal
                Nov 23 '18 at 17:05













              • Yes, "LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0" is a consequence of C11 §6.2.6.2 2. On a pedantic note, LONG_MAX == ULONG_MAX is possible yet not have come across such a machine for decades. IMO, OP's goal lacks clarity for a highly portable solution- yet good enough solutions can be had.

                – chux
                Nov 23 '18 at 17:11





















              • Good approach that does not rely on two's complement internally. Corner oops: "It is UB with 2's complement i == INT_MIN and -num.

                – chux
                Nov 23 '18 at 16:40













              • @chux: I'm sure you mean LONG_MIN, as I'm using long, not int. I'm not sure it is worth avoiding the Undefined Behaviour here, nor how would one do so portably without an even larger integer type. Suggestions?

                – Nominal Animal
                Nov 23 '18 at 16:49











              • Yes LONG_MIN was meant, not INT_MIN. To avoid a larger type, 1 + (~((unsigned long)(-1 - num) + 1)); (correct, but ugly) or other code.

                – chux
                Nov 23 '18 at 17:01











              • @chux: Is there anything in the C standards that says LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0? If not, LONG_MIN is not the only case that needs special care.

                – Nominal Animal
                Nov 23 '18 at 17:05













              • Yes, "LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0" is a consequence of C11 §6.2.6.2 2. On a pedantic note, LONG_MAX == ULONG_MAX is possible yet not have come across such a machine for decades. IMO, OP's goal lacks clarity for a highly portable solution- yet good enough solutions can be had.

                – chux
                Nov 23 '18 at 17:11



















              Good approach that does not rely on two's complement internally. Corner oops: "It is UB with 2's complement i == INT_MIN and -num.

              – chux
              Nov 23 '18 at 16:40







              Good approach that does not rely on two's complement internally. Corner oops: "It is UB with 2's complement i == INT_MIN and -num.

              – chux
              Nov 23 '18 at 16:40















              @chux: I'm sure you mean LONG_MIN, as I'm using long, not int. I'm not sure it is worth avoiding the Undefined Behaviour here, nor how would one do so portably without an even larger integer type. Suggestions?

              – Nominal Animal
              Nov 23 '18 at 16:49





              @chux: I'm sure you mean LONG_MIN, as I'm using long, not int. I'm not sure it is worth avoiding the Undefined Behaviour here, nor how would one do so portably without an even larger integer type. Suggestions?

              – Nominal Animal
              Nov 23 '18 at 16:49













              Yes LONG_MIN was meant, not INT_MIN. To avoid a larger type, 1 + (~((unsigned long)(-1 - num) + 1)); (correct, but ugly) or other code.

              – chux
              Nov 23 '18 at 17:01





              Yes LONG_MIN was meant, not INT_MIN. To avoid a larger type, 1 + (~((unsigned long)(-1 - num) + 1)); (correct, but ugly) or other code.

              – chux
              Nov 23 '18 at 17:01













              @chux: Is there anything in the C standards that says LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0? If not, LONG_MIN is not the only case that needs special care.

              – Nominal Animal
              Nov 23 '18 at 17:05







              @chux: Is there anything in the C standards that says LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0? If not, LONG_MIN is not the only case that needs special care.

              – Nominal Animal
              Nov 23 '18 at 17:05















              Yes, "LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0" is a consequence of C11 §6.2.6.2 2. On a pedantic note, LONG_MAX == ULONG_MAX is possible yet not have come across such a machine for decades. IMO, OP's goal lacks clarity for a highly portable solution- yet good enough solutions can be had.

              – chux
              Nov 23 '18 at 17:11







              Yes, "LONG_MIN+LONG_MAX cannot be less than -1, or greater than 0" is a consequence of C11 §6.2.6.2 2. On a pedantic note, LONG_MAX == ULONG_MAX is possible yet not have come across such a machine for decades. IMO, OP's goal lacks clarity for a highly portable solution- yet good enough solutions can be had.

              – chux
              Nov 23 '18 at 17:11













              0














              % is the remainder function, not mod.



              With b==2, i%b returns [-1, 0, 1]. This is not the needed functionality for str[e] = (i%b) + '0'; See ... difference between “mod” and “remainder”



              This is the cause of '/' and "also gives out characters below the '/' ".





              Build up the string from the "right"



              With a 2's complement int, a simple approach is to convert to unsigned and avoid a negative result from %. Since code is using % to extract the least significant digit, walk the buffer from right to left.



              #include <limits.h>

              ...
              unsigned u = i;

              // make a temporary buffer large enough for any string output in binary
              // v------v Size of `u` in "bytes"
              // | | v------v Size of a "byte" - commonly 8
              char my_buff[sizeof u & CHAR_BIT + 1];
              int e = 0;

              // Form a pointer to the end so code assigns the least significant digits on the right
              char *p = &my_buff[sizeof my_buff - 1];

              // Strings are null character terminated
              *p = '';

              // Use a `do` loop to insure at least one pass. Useful when `i==0` --> "0"
              do {
              p--;
              p[e] = "0123456789ABCDEF"[u%b]; // Select desired digit
              u = u / b;
              } while (u);

              // "prepend" characters as desired
              if(b == 16){
              *(--p) = 'x';
              *(--p) = '0';
              }
              else if(b == 8 && i != 0){
              *(--p) = '0';
              }

              strcpy(str, p);





              share|improve this answer






























                0














                % is the remainder function, not mod.



                With b==2, i%b returns [-1, 0, 1]. This is not the needed functionality for str[e] = (i%b) + '0'; See ... difference between “mod” and “remainder”



                This is the cause of '/' and "also gives out characters below the '/' ".





                Build up the string from the "right"



                With a 2's complement int, a simple approach is to convert to unsigned and avoid a negative result from %. Since code is using % to extract the least significant digit, walk the buffer from right to left.



                #include <limits.h>

                ...
                unsigned u = i;

                // make a temporary buffer large enough for any string output in binary
                // v------v Size of `u` in "bytes"
                // | | v------v Size of a "byte" - commonly 8
                char my_buff[sizeof u & CHAR_BIT + 1];
                int e = 0;

                // Form a pointer to the end so code assigns the least significant digits on the right
                char *p = &my_buff[sizeof my_buff - 1];

                // Strings are null character terminated
                *p = '';

                // Use a `do` loop to insure at least one pass. Useful when `i==0` --> "0"
                do {
                p--;
                p[e] = "0123456789ABCDEF"[u%b]; // Select desired digit
                u = u / b;
                } while (u);

                // "prepend" characters as desired
                if(b == 16){
                *(--p) = 'x';
                *(--p) = '0';
                }
                else if(b == 8 && i != 0){
                *(--p) = '0';
                }

                strcpy(str, p);





                share|improve this answer




























                  0












                  0








                  0







                  % is the remainder function, not mod.



                  With b==2, i%b returns [-1, 0, 1]. This is not the needed functionality for str[e] = (i%b) + '0'; See ... difference between “mod” and “remainder”



                  This is the cause of '/' and "also gives out characters below the '/' ".





                  Build up the string from the "right"



                  With a 2's complement int, a simple approach is to convert to unsigned and avoid a negative result from %. Since code is using % to extract the least significant digit, walk the buffer from right to left.



                  #include <limits.h>

                  ...
                  unsigned u = i;

                  // make a temporary buffer large enough for any string output in binary
                  // v------v Size of `u` in "bytes"
                  // | | v------v Size of a "byte" - commonly 8
                  char my_buff[sizeof u & CHAR_BIT + 1];
                  int e = 0;

                  // Form a pointer to the end so code assigns the least significant digits on the right
                  char *p = &my_buff[sizeof my_buff - 1];

                  // Strings are null character terminated
                  *p = '';

                  // Use a `do` loop to insure at least one pass. Useful when `i==0` --> "0"
                  do {
                  p--;
                  p[e] = "0123456789ABCDEF"[u%b]; // Select desired digit
                  u = u / b;
                  } while (u);

                  // "prepend" characters as desired
                  if(b == 16){
                  *(--p) = 'x';
                  *(--p) = '0';
                  }
                  else if(b == 8 && i != 0){
                  *(--p) = '0';
                  }

                  strcpy(str, p);





                  share|improve this answer















                  % is the remainder function, not mod.



                  With b==2, i%b returns [-1, 0, 1]. This is not the needed functionality for str[e] = (i%b) + '0'; See ... difference between “mod” and “remainder”



                  This is the cause of '/' and "also gives out characters below the '/' ".





                  Build up the string from the "right"



                  With a 2's complement int, a simple approach is to convert to unsigned and avoid a negative result from %. Since code is using % to extract the least significant digit, walk the buffer from right to left.



                  #include <limits.h>

                  ...
                  unsigned u = i;

                  // make a temporary buffer large enough for any string output in binary
                  // v------v Size of `u` in "bytes"
                  // | | v------v Size of a "byte" - commonly 8
                  char my_buff[sizeof u & CHAR_BIT + 1];
                  int e = 0;

                  // Form a pointer to the end so code assigns the least significant digits on the right
                  char *p = &my_buff[sizeof my_buff - 1];

                  // Strings are null character terminated
                  *p = '';

                  // Use a `do` loop to insure at least one pass. Useful when `i==0` --> "0"
                  do {
                  p--;
                  p[e] = "0123456789ABCDEF"[u%b]; // Select desired digit
                  u = u / b;
                  } while (u);

                  // "prepend" characters as desired
                  if(b == 16){
                  *(--p) = 'x';
                  *(--p) = '0';
                  }
                  else if(b == 8 && i != 0){
                  *(--p) = '0';
                  }

                  strcpy(str, p);






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 23 '18 at 16:37

























                  answered Nov 23 '18 at 16:30









                  chuxchux

                  85.3k874157




                  85.3k874157






























                      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%2f53446176%2fconverting-a-negative-decimal-into-binary-in-c%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

                      Paul Cézanne

                      UIScrollView CustomStickyHeader Resize height generates problems when scroll is too fast

                      Angular material date-picker (MatDatepicker) auto completes the date on focus out