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;
}
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
add a comment |
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
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
add a comment |
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
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
c binary decimal
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
add a comment |
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
add a comment |
3 Answers
3
active
oldest
votes
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
add a comment |
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;
}
Good approach that does not rely on two's complement internally. Corner oops: "It is UB with 2's complementi == INT_MINand-num.
– chux
Nov 23 '18 at 16:40
@chux: I'm sure you meanLONG_MIN, as I'm usinglong, notint. 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
YesLONG_MINwas meant, notINT_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 saysLONG_MIN+LONG_MAXcannot be less than -1, or greater than 0? If not,LONG_MINis 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_MAXis 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
|
show 1 more comment
% 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);
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
add a comment |
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
add a comment |
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
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
answered Nov 23 '18 at 12:04
StrikholStrikhol
365
365
add a comment |
add a comment |
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;
}
Good approach that does not rely on two's complement internally. Corner oops: "It is UB with 2's complementi == INT_MINand-num.
– chux
Nov 23 '18 at 16:40
@chux: I'm sure you meanLONG_MIN, as I'm usinglong, notint. 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
YesLONG_MINwas meant, notINT_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 saysLONG_MIN+LONG_MAXcannot be less than -1, or greater than 0? If not,LONG_MINis 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_MAXis 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
|
show 1 more comment
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;
}
Good approach that does not rely on two's complement internally. Corner oops: "It is UB with 2's complementi == INT_MINand-num.
– chux
Nov 23 '18 at 16:40
@chux: I'm sure you meanLONG_MIN, as I'm usinglong, notint. 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
YesLONG_MINwas meant, notINT_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 saysLONG_MIN+LONG_MAXcannot be less than -1, or greater than 0? If not,LONG_MINis 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_MAXis 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
|
show 1 more comment
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;
}
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;
}
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 complementi == INT_MINand-num.
– chux
Nov 23 '18 at 16:40
@chux: I'm sure you meanLONG_MIN, as I'm usinglong, notint. 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
YesLONG_MINwas meant, notINT_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 saysLONG_MIN+LONG_MAXcannot be less than -1, or greater than 0? If not,LONG_MINis 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_MAXis 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
|
show 1 more comment
Good approach that does not rely on two's complement internally. Corner oops: "It is UB with 2's complementi == INT_MINand-num.
– chux
Nov 23 '18 at 16:40
@chux: I'm sure you meanLONG_MIN, as I'm usinglong, notint. 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
YesLONG_MINwas meant, notINT_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 saysLONG_MIN+LONG_MAXcannot be less than -1, or greater than 0? If not,LONG_MINis 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_MAXis 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
|
show 1 more comment
% 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);
add a comment |
% 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);
add a comment |
% 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);
% 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);
edited Nov 23 '18 at 16:37
answered Nov 23 '18 at 16:30
chuxchux
85.3k874157
85.3k874157
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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