I want to convert a number x of a base n to a string and store it in str. str has the max size of max. In this program I don't want to use any library functions. If I reach the maximum size of the array, the function should return false and the array contents should be undefined.
The prototype of the function looks like this:
bool num2str(int x, char *str, unsigned n, unsigned max);
How would I go about making this work? I'm having trouble understanding the algorithm behind it.
I also need to check the value of n, but I already did that:
bool num2str(int x, char *str, unsigned n, unsigned max)
{
assert(n >= 2 && n <= 36);
return true;
}
But that's all I could do. Please help.
Let's take a number in base 10: 123456. Now let's repeatedly apply a modulus and an integer division using the number and base 10:
123456 mod 10 = 6
123456 div 10 = 12345
12345 mod 10 = 5
12345 div 10 = 1234
As you can see, modulus by base extracts the last digit, while integer division by base shifts the number on digit to the right. You can do the same for any base. Hope this hint is enough.
Related
I was working on a question using C language. The problem was "to determine whether a number n is divisible by 15 or not". The range of n was [1 to 101000]. There is no data type in C which can do the needful, so what should I do ?
Yes, there is no datatype built in to handle that and you don't need one to detect whether a number is divisible by 15 or not. Just get those digits in a string (NUL terminated char array in c) and check whether the last digit (least significant digit) is 5 or 0 and also check whether the digit sum of those digits, which constitute the number, (it would be as per your need - roughly at max 10001 digits) is divisible by 3 or not. If both conditions are satisfied which is the criteria to be divisible by 15(as the prime factors of 15 is 3 and 5 which dictates a number divisible by 15 should be divisible by 3 and 5 both), it is divisible by 15.
"to determine whether a number n is divisible by 15 or not"
Is is not too hard to make this more general and answer the question:
"to determine whether a number N is divisible by M or not"
Encode the large integer N as a string of decimal digits. Perform modulo math (%) on each digit, scaling the prior result by 10. Then check if the final result is 0.
y = (y * 10 + digit) % m;
Simple function call
unsigned string_mod(const char *s, unsigned m) {
unsigned y = 0;
while (*s) {
unsigned digit = (unsigned) (*s++ - '0');
y = (y * 10 + digit) % m;
}
return y;
}
Test code
void test(const char *s, unsigned m) {
printf("%s is%s divisible by %u\n",
s, string_mod(s,m) == 0 ? "" : " not", m);
}
int main(void) {
test("100",3);
test("123456",3);
test("100",15);
test("105",15);
// Make big numbers
char buffer[1001+1];
sprintf(buffer, "1%01000d", 0);
test(buffer,15);
sprintf(buffer, "1%0999d5", 0);
test(buffer,15);
}
Output
100 is not divisible by 3
123456 is divisible by 3
100 is not divisible by 15
105 is divisible by 15
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 is not divisible by 15
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005 is divisible by 15
you can use some "BigInt" library
like https://gmplib.org/ just googling "BigInt C library" will give a lot of examples.
According to the task as you said it... most probably it indeed was especially composed in such a way that you have not to look for a straightforward answer but cheat somehow
I'm new to programming and stuck in a problem.
I have a long variable of any length.
I want to extract any number of digits of this number.
An Example: Number = 135678256 and I want the first two digits, here 13.
I added some pseudo-code, which shall represent my first idea.
int digits(long n){
int x = n / (10^ length(long n)) ;
int y = n / (10^(length(long n)-1)) ;
y = x-y;
return x,y};
length is a function that returns the length of Number.
How to change my code efficiently to get the fourth and fifth digits?
Thanks a lot!
This question already has answers here:
convert an integer number into an array
(8 answers)
Closed 7 years ago.
So lets say you have an integer in your code declared
int my_num = 967892;
and you have an array
int a[6];
How would you put that integer into the array so it looks like this?
{ 9, 6, 7, 8, 9, 2 }
Perhaps like this:
const unsigned char digits[] = { 9, 6, 7, 8, 9, 2 };
but there are many things that are unclear with your question, of course.
If you want to do this at runtime, as your comment now makes me believe, you need more code of course. Also, it will be tricky to make the array "fit" the number exactly, since that requires runtime-sizing of the array.
The core operation is % 10, which when applied to a number results in the rightmost digit (the "ones" digit).
You can do this by getting each digit and putting it into an array. Kudos to #unwind for thinking of using unsigned int because digits don't have signs. I didn't think of that.
DISClAIMER: this code is untested but would, theoretically, if I haven't made any mistakes that the community will catch, accomplish your task.
NOTE: This program is implementation-defined when theNum is negative. See this SO question for more info on what that means. Also, the accepted answer in the question of which this post is a duplicate has shorter code than this but uses log10 which (according to commenters) could be inaccurate.
//given theNum as the number
int tmp = theNum;
int magnitude = 0;
//if you keep dividing by 10, you will eventually reach 0 (integer division)
//and that will be the magnitude of the number + 1 (x * 10^n-1)
for (; tmp > 0; magnitude++){ //you could use a while loop but this is more compact
tmp /= 10;
}
//the number of digits is equal to the magnitude + 1 and they have no sign
unsigned int digits[magnitude];
//go backwards from the magnitude to 0 taking digits as you go
for (int i = magnitude - 1; i > 0; i--){
//get the last digit (because modular arithmetic gives the remainder)
int digit = theNum % 10;
digits[i] = digit; //record digit
theNum /= 10; //remove last digit
}
If this shall be done dynamically:
Determine the number of digits as N.
Allocate an array large enough (>=N) to hold the digits.
Loop N times chopping of the digits and storing them in the array allocated under 2.
The least significant digit is num % 10
The next digit can be found by num/=10;
This works for positive numbers, but is implementation defined for negative
I assume you want to achieve something like this:
int arr[SOME_SIZE];
int len = int_to_array(arr,421);
assert(len == 3);
assert(arr[0] == 4);
assert(arr[1] == 2);
assert(arr[1] == 1);
Since this is probably a homework problem, I won't give the full answer, but you'll want a loop, and you'll want a way to get the last decimal digit from an int, and an int with the last digit removed.
So here's a hint:
421 / 10 == 42
421 % 10 == 1
If you want to create an array of the right length, there are various approaches:
you could loop through twice; once to count digits (then create the array); once again to populate
you could populate an array that's bigger than you need, then create a new array and copy in as many members as necessary
you could populate an array that's bigger than you need, then use realloc() or similar (a luxury we didn't used to have!)
I'm trying to a create an algorithm that can convert base 10 numbers into base n numbers, where n is at most 10. However, for some weird reason the following algorithm in C fails at certain critical points for each base. For example, for base 2 and base 3 conversions, all numbers up to and including 1023 and 52,487 work, respectively, but numbers beyond that produce some weird negative result. I can't figure out why this is happening; can anyone help me?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int returnint;
int baseconvert(int number,int base) {
if(number == 0 || base == 10) {
return returnint;
}
returnint = (number % base) + (10 * baseconvert(number / base, base));
return returnint;
}
int main() {
fprintf(stdout,"%d\n",baseconvert(1023,2));
fprintf(stdout,"%d\n",baseconvert(52487,3));
}
EDIT:
Here is the printed result of the above print statements, if that's helpful:
1410065408
-2094967296
Your algorithm is very limited in the range of numbers vs. bases. The smaller the base is the more digits are needed to represent it. And since you store the result in decimal form, you'll waste your available data range very quickly. There is no fundamental data type that can hold the results for all the possible inputs. E.g., maximal 31-bit decimal number (normal integer, dropping the sign bit) will result in 31-digit output!
You have several options to cope with this:
Allocate a stack large enough and push the digits into it. Upon completion, print the stack contents.
Print the digits immediately without saving, this will eliminate the need to allocate anything.
E.g.:
#include <stdio.h>
void baseconvert(int number,int base)
{
if(number > 0)
{
int digit = (number % base);
baseconvert(number / base, base);
printf("%d",digit);
}
else
{
printf("\n");
}
}
int main()
{
baseconvert(1023,2);
baseconvert(52487,3);
}
It appears that the integer value is overflowing. For example, the decimal value 1023 in base two is 1111111111. If it is a 4 byte integer, then it will overflow when trying to "add" one more digit (the max signed integer in this case being 2147483647).
Since it appears your goal is to display a number in a different base, it might make more sense to store the digits in a character array.
On all processors that I know of, integers are already stored in binary form; this implies base 2. This value can be displayed in whatever base you desire, with some work on your part. printf() and friends allow you to easily print in base 10 (%d) and base 16 (%x). It is not difficult to imagine a method that would convert a binary (base 2) integer value into a character representation in base n.
I seriously doubt that you really intend to change the actual value of the integer, as you are doing. Like #ThoAppelsin said above, the number of apples in the bag stays the same, regardless of which base you choose for display.
By simply creating a method that represents (with digits) the integer in any base, you will also solve your overflow problem!
Your result is overflowing the integer range. Try using strings instead. This is the pseudocode which relies on strings to represent numbers and it can convert numbers from any base to any other base between 2 and 36 inclusive (using digits and upper case letters):
function ConvertNumber(number, b, d)
begin
newNumber = ""
while number <> "0"
begin
number = Divide(number, b, d, out remainder)
newDigit = ValueToDigit(remainder)
newNumber = Concatenate(newDigit, newNumber)
end
if newNumber ="" then
newNumber = "0"
end
function Divide(number, base, divisor, out remainder)
begin
remainder = 0
result = ""
for i = 0 to Length(number) - 1
begin
digitValue = DigitToValue(number[i])
remainder = base * remainder + digitValue
newDigitValue = remainder / divisor -- integer division
remainder = remainder mod divisor
if newDigitValue > 0 OR result <> "" then
newDigit = ValueToDigit(newDigitValue)
result = Concatenate(result, newDigit)
end
if result = "" then
result = "0"
return result
end
You can find the whole math and implementation in this article: Converting Number Bases.
itoa is not an ANSI-C standard therefore doesn't work for GCC
char* itoa(int val, int base){
static char buf[32] = {0};
int i = 30;
for(; val && i ; --i, val /= base)
buf[i] = "0123456789abcdef"[val % base];
return &buf[i+1];
}
Questions I have
static char buf[32]
Why use static? Can I delete that?
Why i=30?
Shouldn't it be 31? 0 to 31 for 32 bits.
For the for-loop, what is val /= base trying to do?
Inside the for-loop, what does val%base do? I know it's for remainder but how's that relate to here? What's the difference between val/base versus val%base?
1) as #Blastfurnace noted, the static is needed so that the buffer still exists when the function returns
2) i=30 because its the last used index, because the index 31 needs to be NULL (\0). because c works with Null-Terminated-Strings
3) removing the last digit. i.e: val = 12345, base = 10, val / base = 1234, 5 is removed
4) getting the current digit (right to left) , 12345 % 10 = 5 (its also the index of the char array representing the digits (very efficient)
1)static char buf[32]
why use static? can I delete that?
So it doesn't get reloaded everytime the routine is called. No, the routine needs it to store the ascii values to be output.
2)why i=30?
shouldn't be 31? 0 to 31 for 32 bits
Not sure, but 30 characters represents 120 bits, not 30.
3) for the for loop, what does val /=base trying to do?
It's reducing the base on each iteration so the remainder value (used as an index to the array) will be correct.
4)inside the for loop, what does val%base do? I know it's for remainder but how's that relate to here? what's the difference between val/base versus val%base?
It calculates the remainder as an index into buf, to select the correct ascii value. / returns the integer (rounded off) divide, not the remainder of that divide.
Value = (Value/divisor)*divisor + Value%divisor.
thanks