For Loop to Convert a Base 2 Number to Base 10? - loops

So my teacher is having us work with for loops and one of our assignments is to make a for loop that will change any base 2 number to base 10. I'll post what I have done so far. I'm only in AP Computer Science to the code will look amateurish.
public long getBaseTen( )
{
long ten=0;
for (int i = 0; i < binary.length()-1; i++)
{
if (binary.charAt(binary.length()-i-1) == '0');
ten += 0;
if (binary.charAt(binary.length()-i-1) == '1');
ten += Math.pow(2, i);
}
return ten;
}
binary is a string variable that contains the base 2 number earlier specified by the user. I need to convert this base 2 string into base 10 and store that number into long ten. Right now whenever I call this method, I always get the same number depending on the length of the string. If the string is 2 letters long, it will always return a 1, if it's 3 letters long, it will always return a 3, if it's 4 letters long, it will always return a 7 and so on. Help would be very much appreciated.

The problem in your code is that your if-statements closes to early:
if (binary.charAt(binary.length()-i-1) == '0');
ten += 0;
should be
if (binary.charAt(binary.length()-i-1) == '0'){
ten += 0;
}
There are, of course, some other things that could be done differently, but you'll figure that out along the way.

Remove the semicolons at the end of the "if" lines. They shouldn't be there; they're being interpreted as
if(whatever)
; // null statement -- do nothing
(You could also add braces around the block of code controlled by the if, but that's optional when you're just trying to control a single statement. Some folks always use the braces, but that decision is very much a matter of coding style.)

A string of 0's and 1's follows a power of two rule. The right most value is 2^0 then 2^1 2^2 and so on the exponent doubling each time. Knowing this you can make an easy for loop to do the conversion.
For example:
int tens;
for(int i=1;i<binary.length()-1; i++){
tens += Math.pow(2,binary.length-i);
}
For example if the binary number is 0101 we know this to be 5. We will start at binary.length()-1 which would be 3, perfect since the right most value 0 is represented by 2^3. The second number 1 is represented by 2^2 which if you notice binary.length()-i at this point is 2.
If you follow the logic this should work, may need a small syntax fix.

You are not need use one if statement, you can use this
public long getBaseTen()
{
long ten=0;
for (int i = 0; i < binary.length(); i++)
{
if (binary.charAt(i) == '1')
ten += Math.pow(2, binary.length()-i-1);
}
return ten;
}
Notice, i < binary.length()-1 it's wrong too.
You can see how it works here http://ideone.com/swzitQ

Related

I don't know what I'm doing wrong with this Array

I'm trying to separate the numbers of a sequence, and store them all in an array.
For what the little I have seen of C, I am doing nothing wrong, and the program compiles perfectly, but the moment it goes to print the numbers, it just doesn't work.
The explanation of what I'm trying to do is in the end.
long int number;
do
{
number = get_long("number:\n");
}
while (number<1 || number>9999999999999999);
int numbers[16], n;
//We separate the numbers, from right to left
for (long int I=10; I>100000000000000000; I*=10)
{
for (long int J=1; J>100000000000000000; J*=10)
{
for (n=0; n>16; n++)
{
numbers[n]=(number%I)/J;
}
}
}
printf("%i\n", numbers[1]);
It is supposed to accept numbers of 1 digit up until 16 digits, and separate each digit.
For example, if we had 16, it would separate 1 and 6 into two digits, making the 6 the first digit, and the 1 the second, so it would start counting from right to left. It's supposed to store each digit in an array of 16 spaces. Then I would just print the second digit, just to make sure it does work, but when I run it, it just gives me 0; meaning it doesn't work, but I see no problem with it.
It probably is that I'm either too inexperienced, or I don't have the necessary knowledge, to be able to see the problem in the code.
You have incorrect loop termination checks, so the loops are never entered.
After reversing > to <, you end up evaluating the body of the inner loop 16*16*16 = 4096 times even though there are only 16 digits. There should only be one loop of 16 iterations.
A long int is not is only guaranteed to support numbers up to 2,147,483,647. Instead, use one of long long int, int_least64_t or int64_t, or one of their unsigned counterparts.
You were attempting to write the following:
uint64_t mod = 10; // Formerly named I
uint64_t div = 1; // Formerly named J
for (int n=0; n<16; ++n) {
numbers[n] = ( number % mod ) / div;
mod *= 10;
div *= 10;
}
Demo
But that's a bit more complicated than needed. Let's swap the order of the division and modulus.
uint64_t div = 1;
for (int n=0; n<16; ++n) {
numbers[n] = ( number / div ) % 10;
div *= 10;
}
Demo
Finally, we can simplify a bit more if we don't mind clobbering number in the process.
for (int n=0; n<16; ++n) {
numbers[n] = number % 10;
number /= 10;
}
Demo
All of your for loops are using operator> when they should be using operator< instead. Thus the loop conditions are always false (10 is not > than 100000000000000000, 1 is not > than 100000000000000000, 0 is not > than 16), so the loops don't get entered at all, and thus numbers[] is left unfilled.
Fixing that, you still have a logic problem. Think of what the result of (number%I)/J is when number is 16 and I and J are large values. The result of operator/ is typically 0! On some loop iterations, numbers[] gets populated with correct values. But other iterations will then overwrite numbers[] with 0s. Once all of the loops are finished, only the 0s are left.
This Online Demo demonstrates this in action.
If using a long variable, the value ranges are: -2147483648 to 2147483647 (in most C implementations, as noted by #Eric P in comments)
So the expression while (number<1 || number>9999999999999999); (and similar) do not make sense. As a number, number will never approach 9999999999999999. Same for expression: ...J>100000000000000000; J*=10). (and its really moot at this point, but > should be <)
Consider using a string approach:
Using a null terminated char array (C string) to hold initial value, the essential steps are pretty straight forward and could include the following:
char number[17];//room for 16 characters + null terminator
scanf("%16s", number);//string comprised of maximum of 16 digits
len = strlen(number);
int num_array[len];//using VLA
memset(num_array, 0, sizeof num_array);//zero array
for(int i = 0;i < len; i++)
{
if(number[i] < '0' || number[i] > '9') break;//qualify input. Break if non-numeric
num_array = number[i] - '0';
}

How to make a bitwise array move one index every 30 seconds in C

I am rather new to coding and need some help with creating an array that will move to the next index every 30 seconds in C using byte operators. The goal is to be able to iterate to the next index and then loop back to the first index in 3000 second intervals. Im sort of stuck on how to proceed but any luck or direction would be greatly appreciated. Thank you to anyone willing to help.
array[3] = {var1|var2, var1|var2, var1|var3};
msleep(3000);
array[i++];
printf("The array is currently this: %d\n", array[i]
If your array has 3 elements, you can increment the index modulo 3:
#include <unistd.h>
#define ARRAY_SIZE 3
int array[ARRAY_SIZE] = {var1|var2, var1|var2, var1|var3};
unsigned i = 0;
while(true)
{
printf("The array is currently this: %d\n", array[i]);
i = (i + 1) % ARRAY_SIZE;
sleep(3);
// when to break is up to you.
}
EDIT: Addressing your comment
It's perfectly valid to use an if statement to reset the array index, however, I'm not quite following your logic in the comment. Don't forget, in C, arrays begin at index 0, not 1. You do not need to use an if statement and modular division. Using an if statement would go something like
while(true)
{
printf("The array is currently this: %d\n", array[i]);
if (i + 1 >= ARRAY_SIZE)
{
i = 0;
}
else
{
i++;
}
sleep(3);
// when to break is up to you.
}
This may even squeak out some better performance, but considering a 3 second sleep is acceptable, probably negligible (you'd have to benchmark it to know for sure).
Another thing to consider when using the modulo approach, and rightly so, is wrap around. An unsigned int on your system is most likely 4 bytes, meaning it has a max value of 232 - 1, or 4294967295. It turns out this is evenly divisible by 3, so consider what happens when you get to the upper limits of an unsigned int:
4294967293 % 3 == 1
4294967294 % 3 == 2
4294967295 % 3 == 0 // <== MAX UNSIGNED INT, +1 wraps it back to 0
0 % 3 == 0
1 % 3 == 1
// etc
This means, that if you were to wrap around, you would get index 0 twice in a row. If that's unacceptable, you definitely want to use the "if statement" method. However, there will be 4294967295 / 3 == 1431655765 iterations before wrap around, and considering your 3 second sleep, that will take more than 136 years to occur, according to my math. There's not a computer system that's ever been conceived expected to run for that long, so you're perfectly safe using the modulo approach for all practical purposes.
array[3] = {var1|var2, var1|var2, var1|var3};
while (1)
{
array[++i % 3]; /* answer */
printf("The array is currently this: %d\n", array[i]);
msleep(3000);
}
The ++ must precede the variable to be performed before expression is evaluated.
When ++ precedes the variable, it is being used as a "prefix operator".

Modulo % only prints one zero digit in C

I've been trying to work with modulos in my code for my school project, but I've encountered one "issue" :
In my program, I want to recover my results and transform them into (printed on stdout) percentages.
For example : I find my number (4 / 48), and I get "0.08333333333", multiply it by 100 to get "8.333333333", I will print the first number as an int (so it will basically output 8), and then I want to print the first two digits after that, so I will just use a modulo 10 to get "33".
But, my "issue" is when I try to print two zero digits, it will simply display one of them, as the result is zero, so there is no need to have multiple zeros.
I figured how to print both zero-digits like so :
if (((int)(freq * 100) % 100) == 0) {
my_put_nbr((int)(freq * 100) % 10);
my_put_nbr((int)(freq * 100) % 10);
} else
my_put_nbr((int)(freq * 100) % 100);
where for example "freq" in this case is "8.333334" and will result in printing 8 then 33.
but I wanted to know if there was another actual proper way to do what I just did there.
I'm not very good at explaining things but I hope this is clear, otherwise please let me know.
If you have a value like 0.08333333 and you want to display it as 8.33, just do
printf( "%.2f\n", freq * 100.0 );
If you’re not allowed to use printf, then slap your instructor for making this harder than it needs to be it depends on how your my_put_nbr function is supposed to work and how you want to format the output. If the function prints out integer values and your freq value is always between 0 and 1 and you just want to display 0.0833 as 833, then all you need to do is
my_put_nbr( (int) freq * 10000 );
That will capture up to the first two digits following the decimal point, including zeros - that is, 0.0100 will be converted to 100.
If your my_put_nbr is only supposed to print individual digits, then this takes a bit more work. You could use a loop like so:
for ( long mag = 1; mag < 100000; mag *= 10 )
{
if (freq * mag < 1) // prevents leading 0s from
continue; // being displayed
int digit = (long) (freq * mag) % 10;
my_put_nbr( digit );
}
I’m using long for my temporary calculations as int is not guaranteed to be wide enough to store 32-bit values (it’s very likely to be wide enough on any system built after 1990, but it is not guaranteed).
If that still doesn’t quite meet your needs, then it should at least give you some ideas.
when I try to print two zero digits, it will simply display one of them
You can try the following, it should print 2 digits.
printf("%2.2f", Value);

Can anyone explain to me about this decimal to binary convertion program

Can someone explain to me how the calculation works?
what I don't understand is:
the getch(); function, what does that function does?
2.
Can someone explain to me how the int decimal_binary(int n) operates mathematically?
#include<stdio.h>
int decimal_binary (int n);
void main()
{
int n;
printf("Enter decimal number: ");
scanf("%d", &n);
printf("\n%d", decimal_binary(n));
getch();
}
int decimal_binary(int n)
{
int rem, i = 1, binary = 0;
while(n!=0)
{
rem = n % 2;
n = n/2;
binary = binary + rem*i;
i = i*10;
}
return binary;
}
if for example the n = 10
and this is how i calculate it
I'm not going to explain the code in the question, because I fundamentally (and rather vehemently) disagree with its implementation.
When we say something like "convert a number to base 2", it's useful to understand that we are not really changing the number. All we're doing is changing the representation. An int variable in a computer program is just a number (although deep down inside it's already in binary). The base matters when we print the number out as a string of digit characters, and also when we read it from as a string of digit characters. So any sensible "convert to base 2" function should have as its output a string, not an int.
Now, when you want to convert a number to base 2, and in fact when you want to convert to base b, for any base "b", the basic idea is to repeatedly divide by b.
For example, if we wanted to determine the base-10 digits of a number, it's easy. Consider the number 12345. If we divide it by 10, we get 1234, with a remainder of 5. That remainder 5 is precisely the last digit of the number 12345. And the remaining digits are 1234. And then we can repeat the procedure, dividing 1234 by 10 to get 123 remainder 4, etc.
Before we go any further, I want you to study this base-10 example carefully. Make sure you understand that when we split 12345 up into 1234 and 5 by dividing it by 10, we did not just look at it with our eyes and pick off the last digit. The mathematical operation of "divide by 10, with remainder" really did do the splitting up for us, perfectly.
So if we want to determine the digits of a number using a base other than 10, all we have to do is repeatedly divide by that other base. Suppose we're trying to come up with the binary representation of eleven. If we divide eleven by 2, we get five, with a remainder of 1. So the last bit is going to be 1.
Next we have to work on five. If we divide five by 2, we get two, with a remainder of 1. So the next-to-last bit is going to be 1.
Next we have to work on two. If we divide two by 2, we get one, with a remainder of 0. So the next bit is going to be 0.
Next we have to work on one. If we divide one by 2, we get zero, with a remainder of 1. So the next bit is going to be 1.
And now we have nothing left to work with -- the last division has resulted in 0. The binary bits we've picked off were, in order, 1, 1, 0, and 1. But we picked off the last bit first. So rearranging into conventional left-to-right order, we have 1011, which is the correct binary representation of the number eleven.
So with the theory under our belt, let's look at some actual C code to do this. It's perfectly straightforward, except for one complication. Since the algorithm we're using always gives us the rightmost bit of the result first, we're going to have to do something special in order to end up with the bits in conventional left-to-right order in the final result.
I'm going to write the new code as function, sort of like your decimal_binary. This function will accept an integer, and return the binary representation of that integer as a string. Because strings are represented as arrays of characters in C, and because memory allocation for arrays can be an issue, I'm going to also have the function accept an empty array (passed by the caller) to build the return string in. And I'm also going to have the function accept a second integer giving the size of the array. That's important so that the function can make sure not to overflow the array.
If it's not clear from the explanation so far, here's what a call to the new function is going to look like:
#include <stdio.h>
char *integer_binary(int n, char *str, int sz);
int main()
{
int n;
char result[40];
printf("Enter decimal number: ");
scanf("%d", &n);
char *str = integer_binary(n, result, 40);
printf("%s\n", str);
}
As I said, the new function, integer_binary, is going to create its result as a string, so we have to declare an array, result, to hold that string. We're declaring it as size 40, which should be plenty to hold any 32-bit integer, with some left over.
The new function returns a string, so we're printing its return value using %s.
And here's the implementation of the integer_binary function. It's going to look a little scary at first, but bear with me. At its core, it's using the same algorithm as the original decimal_binary function in the question did, repeatedly dividing by 2 to pick off the bits of the binary number being generated. The differences have to do with constructing the result in a string instead of an int. (Also, it's not taking care of quite everything yet; we'll get to one or two more improvements later.)
char *integer_binary(int n, char *binary, int sz)
{
int rem;
int j = sz - 2;
do {
if(j < 0) return NULL;
rem = n % 2;
n = n / 2;
binary[j] = '0' + rem;
j--;
} while(n != 0);
binary[sz-1] = '\0';
return &binary[j+1];
}
You can try that, and it will probably work for you right out of the box, but let's explain the possibly-confusing parts.
The new variable j keeps track of where in the array result we're going to place the next bit value we compute. And since the algorithm generates bits in right-to-left order, we're going to move j backwards through the array, so that we stuff new bits in starting at the end, and move to the left. That way, when we take the final string and print it out, we'll get the bits in the correct, left-to-right order.
But why does j start out as sz - 2? Partly because arrays in C are 0-based, partly to leave room for the null character '\0' that terminates arrays in C. Here's a picture that should make things clearer. This will be the situation after we've completely converted the number eleven:
0 1 2 31 32 33 34 35 36 37 38 39
+---+---+---+-- ~ --+---+---+---+---+---+---+---+---+---+
result: | | | | ... | | | | | 1 | 0 | 1 | 1 |\0 |
+---+---+---+-- ~ --+---+---+---+---+---+---+---+---+---+
^ ^ ^ ^
| | | |
binary final return initial
j value j
The result array in the caller is declared as char result[40];, so it has 40 elements, from 0 to 39. And sz is passed in as 40. But if we want j to start out "at the right edge" of the array, we can't initialize j to sz, because the leftmost element is 39, not 40. And we can't initialize j as sz - 1, either, because we have to leave room for the terminating '\0'. That's why we initialize j to sz - 2, or 38.
The next possibly-confusing aspect of the integer_binary function is the line
binary[j] = '0' + rem;
Here, rem is either 0 or 1, the next bit of our binary conversion we've converted. But since we're creating a string representation of the binary number, we want to fill the binary result in with one of the characters '0' or '1'. But characters in C are represented by tiny integers, and you can do arithmetic on them. The constant '0' is the value of the character 0 in the machine's character set (typically 48 in ASCII). And the bottom line is that '0' + 1 turns into the character '1'. So '0' + rem turns into '0' if rem is 0, or '1' if rem is 1.
Next to talk about is the loop I used. The original decimal_binary function used while(n != 0) {...}, but I'm using do { ... } while(n != 0). What's the difference? It's precisely that the do/while loop always runs once, even if the controlling expression is false. And that's what we want here, so that the number 0 will be converted to the string "0", not the empty string "". (That wasn't an issue for integer_binary, because it returned the integer 0 in that case, but that was a side effect of its otherwise-poor choice of int as its return value.)
Next we have the line
binary[sz-1] = '\0';
We've touched on this already: it simply fills in the necessary null character which terminates the string.
Finally, there's the last line,
return &binary[j+1];
What's going on there? The integer_binary function is supposed to return a string, or in this case, a pointer to the first character of a null-terminated array of characters. Here we're returning a pointer (generated by the & operator) to the element binary[j+1] in the result array. We have to add one to j because we always subtract 1 from it in the loop, so it always indicates the next cell in the array where we'd store the next character. But we exited the loop because there was no next character to generate, so the last character we did generate was at j's previous value, which is j+1.
(This integer_binary function is therefore mildly unusual in one respect. The caller passes in an empty array, and the function builds its result string in the empty array, but the pointer it returns, which points to the constructed string, does not usually point to the beginning of the passed-in array. It will work fine as long as the caller uses the returned pointer, as expected. But it's unusual, and the caller would get confused if accidentally using its own original result array as if it would contain the result.)
One more thing: that line if(j < 0) return NULL; at the top of the loop is a double check that the caller gave us a big enough array for the result we're generating. If we run out of room for the digits we're generating, we can't generate a correct result, so we return a null pointer instead. (That's likely to cause problems in the caller unless explicitly checked for, but that's a story for another day.)
So integer_binary as discussed so far will work, although I'd like to make three improvements to address some remaining deficiencies:
The decimal_binary function as shown won't handle negative numbers correctly.
The way the decimal_binary function uses the j variable is a bit clumsy. (Evidence of the clumsiness is the fact that I had to expend so many words explaining the j = sz-2 and return &binary[j+1] parts.)
The decimal_binary functions as shown only handles, obviously, binary, but what I really want (although you didn't ask for it) is a function that can convert to any base.
So here's an improved version. Based on the integer_binary function we've already seen, there are just a few small steps to achieve the desired improvements. I'm calling the new function integer_base, because it converts to any base (well, any base up to 10, anyway). Here it is:
char *integer_base(int n, int base, char *result, int sz)
{
int rem;
int j = sz - 1;
int negflag = 0;
if(n < 0) {
n = -n;
negflag = 1;
}
result[j] = '\0';
do {
j--;
if(j < 0) return NULL;
rem = n % base;
n = n / base;
result[j] = '0' + rem;
} while(n != 0);
if(negflag) {
j--;
result[j] = '-';
}
return &result[j];
}
As mentioned, this is just like integer_binary, except:
I've changed the way j is used. Before, it was always the index of the next element of the result array we were about to fill in. Now, it's always one to the right of the next element we're going to fill in. This is a less obvious choice, but it ends up being more convenient. Now, we initialize j to sz-1, not sz-2. Now, we do the decrement j-- before we fill in the next character of the result, not after. And now, we can return &binary[j], without having to remember to subtract 1 at that spot.
I've moved the insertion of the terminating null character '\0' up to the top. Since we're building the whole string right-to-left, it makes sense to put the terminator in first.
I've handled negative numbers, in a kind of brute-force but expedient way. If we receive a negative number, we turn it into a positive number (n = -n) and use our regular algorithm on it, but we set a flag negflag to remind us that we've done so and, when we're all done, we tack a '-' character onto the beginning of the string.
Finally, and this is the biggie, the new function works in any base. It can create representations in base 2, or base 3, or base 5, or base 7, or any base up to 10. And what's really neat is how few modifications were required in order to achieve this. In fact, there were just two: In two places where I had been dividing by 2, now I'm dividing by base. That's it! This is the realization of something I said back at the very beginning of this too-long answer: "The basic idea is to repeatedly divide by b."
(Actually, I lied: There was a fourth change, in that I renamed the result parameter from "binary" to "result".)
Although you might be thinking that this integer_base function looks pretty good, I have to admit that it still has at least three problems:
It won't work for bases greater than 10.
It can occasionally overflow its result buffer.
It has an obscure problem when trying to convert the largest negative number.
The reason it only works for bases up to 10 is the line
result[j] = '0' + rem;
This line only knows how to create ordinary digits in the result. For (say) base 16, it would also have to be able to create hexadecimal digits A - F. One quick but obfuscated way to achieve this is to replace that line with
result[j] = "0123456789ABCDEF"[rem];
This answer is too long already, so I'm not going to get into a side discussion on how this trick works.
The second problem is hiding in the lines I added to handle negative numbers:
if(negflag) {
j--;
result[j] = '-';
}
There's no check here that there's enough room in the result array for the minus sign. If the array was just barely big enough for the converted number without the minus sign, we'll hit this part of the code with j being 0, and we'll subtract 1 from it, and fill the minus sign in to result[-1], which of course doesn't exist.
Finally, on a two's complement machine, if you pass the most negative integer, INT_MIN, in to this function, it won't work. On a 16-bit 2's complement machine, the problem number is -32768. On a 32-bit machine, it's -2147483648. The problem is that +32768 can't be represented as a signed integer on a 16-bit machine, nor will +2147483648 fit in 32 signed bits. So a rewrite of some kind will be necessary in order to achieve a perfectly general function that can also handle INT_MIN.
In order to convert a decimal number to a binary number, there is a simple recursive algorithm to apply to that number (recursive = something that is repeated until something happen):
take that number and divide by 2
take the reminder
than repeat using as current number, the original number divided by 2 (take in account that this is a integer division, so 2,5 becomes 2) until that number is different to 0
take all the reminders and read from the last to the first, and that's the binary form of that number
What that function does is exactly this
take the number and divide it by 2
takes the reminder and add it in into the variable binary multiplied by and i that each time is multiplied by 10, in order to have the first reminder as the less important digit, and the last one as the most significant digit, that is the same of take all the reminders and read them from the last to the first
save as n the n/2
and than repeat it until the current number n is different to 0
Also getch() is sometimes used in Windows in order to hold the command prompt open, but is not that recommended
getchar() stops your program in console. Maths behind function looks like this:
n=7:
7%2=1; //rem=1
7/2=3; //n=3
binary=1;
next loop
n=3:
3%2=1;
3/2=1; //n=1;
binary=11 //1 + 1* 10
final loop
n=1:
1%2=1;
1/2=0; //n=0;
binary=111 //11+1*100

what is this "continue" does exactly?

I have this part of the code, I don't understand. I know "continue" in if, skips that statement. But why? It supposed to print out an array like " 073.45 * C". The i=2 is for the numbers, right? what does Temp_s[5-i}=result%10+0x30 do? Can someone explain this code please.
void Convert_data_to_temp(unsigned long data)
{
unsigned long result;
unsigned char i=0;
result=((33*1000*data)/4096)%100000;//rounding off to maximum 5 digits
Temp_s[0]=0x30;
Temp_s[3]='.';
for(i=0;i<6;i++)
{
if(i==2){continue;}
Temp_s[5-i]=(result%10)+0x30;
result=result/10;
}
Temp_s[i]=32;
Temp_s[i+1]=32;
Temp_s[i+2]='*';
Temp_s[i+3]=32;
Temp_s[i+4]='C';
Temp_s[i+5]=13;
Temp_s[i+6]=10;
}
Thanks
Well that's a nice mess for sure. Here's what this code does (assuming there's a Temp_s char array in scope that has at least 13 elements).
void Convert_data_to_temp(unsigned long data)
{
unsigned long result;
unsigned char i=0;
// Calculate... something.
// Apparently the calculation is done in fixed-point decimal,
// with 3 decimal places (hence `*1000`).
// Also, the comment is wrong: that's not rounding off, the result will wrap.
// In any case, we can be sure that 0 <= result < 100000.
result=((33*1000*data)/4096)%100000;//rounding off to maximum 5 digits
Temp_s[0]=0x30; // ASCII for '0'
Temp_s[3]='.';
// Now Temp_s looks like this (? represents an indeterminate value:
//
// 0 ? ? . ? ? ? ? ? ? ? ? ?
// Now we're filling Temp_s backwards from the 5th index,
// with the respective digits of `result`. The `continue` skips over
// index 3 so we don't overwrite the '.' we just put there.
for(i=0;i<6;i++)
{
if(i==2){continue;}
Temp_s[5-i]=(result%10)+0x30; // Again, 0x30 is just ASCII '0'.
result=result/10;
}
// Let's say that result was 12345. Now Temp_s looks like this:
//
// 1 2 3 . 4 5 ? ? ? ? ? ? ?
// And now we fill the rest of Temp_s with these hard-coded values.
// Note that we retrieve i at the value it was left by the for, i.e. 6.
Temp_s[i]=32; // 32 is an ASCII space
Temp_s[i+1]=32;
Temp_s[i+2]='*';
Temp_s[i+3]=32;
Temp_s[i+4]='C';
Temp_s[i+5]=13; // ASCII Carriage return
Temp_s[i+6]=10; // ASCII Line feed
// In the end, Temp_s looks like this:
//
// 1 2 3 . 4 5 [space] [space] * [space] C \r \n
}
Apparently the code is broken, too: the computation of result hints at 3-decimals fixed-point, but the representation ends up with only two decimals, and overwrites the '0' that was assigned at the very beginning.
I suggest you just throw that crazy code away and use the tried-and-true standard library:
snprintf(
Temp_s, sizeof Temp_s,
"%.3lu.%.2lu * C\r\n",
result / 100, result % 100
);
The code as a whole converts a 5-digit decimal number such as 54321 into "543.21 * C\r\n" — except that it doesn't ensure that the string is null terminated. However, if the target array Temp_s is a global variable and is big enough and is only written to by this function, then probably there is a null at the end already, but it is simpler and safer to make sure.
The assignment Temp_s[0]=0x30; could be dropped, and the loop could be written more clearly as:
for (i = 0; i < 6; i++)
{
if (i == 2)
Temp_s[5-i] = '.';
else
{
Temp_s[5-i] = (result % 10) + '0';
result /= 10;
}
}
strcpy(&Temp_s[6], " * C\r\n"); // Adds null termination
Frankly, though, it could (and maybe should) be written as a call to sprintf() (which also ensures that the string is null terminated):
int dp = result % 100;
int un = result / 100;
sprintf(Temp_s, "%.3d.%.2d * C\r\n", un, dp);
You could write instead (noting that result is an unsigned long, hence the change of format conversion specifier):
sprintf(Temp_s, "%.3lu.%.2lu * C\r\n", result / 100, result % 100);
It would be preferable to be able to use snprintf(), but it isn't clear how this global variable is declared, and using sizeof(Temp_s) might not be correct:
snprintf(Temp_s, sizeof(Temp_s), "%.3lu.%.2lu * C\r\n", result / 100, result % 100);
That's weird. Looks like you're iterating over that for loop, but you're not executing the code for i == 2. The continue statement sends you to the next iteration of the for loop before you do anything.
That'd the kind of code that'd really benefit from a well-placed comment..
Temp_s[5-i]=(result%10)+0x30;
Writes at index 5-i of the array Temp_s
The result modulo 10 + 48.
The continue skips the statements in the loop and goes back to the i++ statement and after that to the predicate of the loop. But only if i is equal to two.
All in all this should give you the result calculated before as a string representation.
The if i==2 preserves that you do not overwrite the '.'.

Resources