Decimal precision using integer - c

I am programming a uC in C language and I need to show a float number with 4 precision digits. The thing here is that my number is not really a float type. I have the integer part and the decimal part of the number in two different integer variables. Let say: int digit and int decimal.
I tried using printf ("%d.%d"); That works fine when my decimal number is 6524, but the problem comes when it is exactly 65 since it doesnt show 4 decimals.
I tried using printf ("%d.%04d"); but when my decimal part is exactly 65 it shows 0065 which is not mathematically correct (I would need 6500)
I looked for any argument of printf which completes with zeros at the end but could not find anything. All of them complete with leading zeros which is not useful for me in this case.
I also though about checking if my number is minor that 10, 100 or 1000 and multiply it by 1000, 100 or 10 respectively. But it will not work when the decimal part is exactly 0, since 0*1000 will still be 0 and not 0000.
Any idea on how to solve this? Please let me know if I am not completely clear and I will provide more information
Thanks!

Since printf returns the number of characters printed, you can do it, somewhat clumsily, as follows:
printf("%d.", int_part);
int digits = printf("%d", frac_part);
while (digits++ < 4) putchar('0');
I have to say, though, that it is a very eccentric form of representing a floating point number, and you might seriously want to rethink it.

Another wired possibility is to convert the decimal part to a string and then fill it with 0:
int main() {
int i, d, len;
char p[10];
i = 189;
d = 51;
// convert the number to string and count the digits
snprintf(p, 10, "%d", d);
len = strlen(p);
while (len < 4) {p[len] = '0'; len++;}
p[len] = '\0';
fprintf(stdout, "%d.%s\n", i, p);
// you can also go back to int
d = atoi(p);
fprintf(stdout, "%d.%d\n", i, d);
}

Combine both your answers: multiply by 10, 100 or 1000 as necessary, but still print with %04d.

Related

I'm trying to make a function that prints a floating point numbers without using any standard library functions in C

void putfnbr(float number)
{
int a = (int) number;
putnbr(a);
write(1, ".", 1);
int i = 6;
while (i > 0)
{
number = (number - a) * (10);
a = (int) number;
putnbr(a);
i--;
}
}
putfnbr(123.456555);// output 123.456558
printf("\n%f", 123.456555); // output 123.456555
this function works well however the last number
it's converting to another number in this example:
5 becomes 8,
I want it to print the whole number as it's as the printf() dose
The problem is that the closest float value to the number 123.456555 is actually 123.4565582275390625 (0x1.edd384p+6), so that is what you get when you print it.
The printf format %f prints a double, for which the closest value is 123.4565549999999944930095807649195194244384765625 (0x1.edd38327674d1p+6) so when you print rounded to 6 decimal places (the default with %f) you get what you see.
If you change your putfnbr routine to use a double instead of a float, you'll print the value 123.456554, because you are always rounding towards zero -- you really should be rounding the last digit to the nearest integer. Unfortunately that turns out to be very hard to do while still getting all the corner cases right.
One other note -- your code will misbehave for negative numbers as written.

Performing a sum between two arrays of digis

Had an interview today and I was asked the following question - given two arrays arr1 and arr2 of chars where they contain only numbers and one dot and also given a value m, sum them into one array of chars where they contain m digits after the dot. The program should be written in C. The algorithm was not important for them, they just gave me a compiler and 20 minutes to pass their tests.
First of all I though to find the maximum length and iterate through the array from the end and sum the values while keeping the carry:
int length = (firstLength < secondLength) ? secondLength : firstLength;
char[length] result;
for (int i = length - 1; i >= 0; i--) {
// TODO: add code
}
The problem is that for some reason I'm not sure what is the right way to perform that sum while keeping with the dot. This loop should just perform the look and not counter to k. I mean that at this point I thought just adding the values and at the end i'll insert another loop which will print k values after the dot.
My question is how should look the first loop I mentioned (the one that actually sums), I'm really got stuck on it.
The algorithm was not important
Ok, I'll let libc do it for me in that case (obviously error handling is missing):
void sum(char *as, char *bs, char *out, int precision)
{
float a, b;
sscanf(as, "%f", &a);
sscanf(bs, "%f", &b);
a += b;
sprintf(out, "%.*f", precision, a);
}
It actually took me a lot longer than 20 mins to do this. The code is fairly long too so I don't plan on posting it here. In a nutshell, the code does:
normalize the 2 numbers into 2 new strings so they have the same number of decimal digits
allocate a new string with length of longer of the 2 strings above + 1
add the 2 strings together, 2 digits at a time, with carrier
it is not clear if the final answer needs to be rounded. If not, just expand/truncate the decimals to m digits. Remove any leading zero if needed.
I am not sure whether this is the best solution or not but here's a solution and I hope it helps.
#include<stdio.h>
#include<math.h>
double convertNumber(char *arr){
int i;
int flag_d=0; //To check whether we are reading digits before or after decimal
double a=0;
int j=1;
for(i=0;i<arr[i]!='\0';i++){
if(arr[i] !='.'){
if(flag_d==0)
a = a*10 + arr[i]-48;
else{
a = a + (arr[i]-48.0)/pow(10, j);
j++;
}
}else{
flag_d=1;
}
}
return a;
}
int main() {
char num1[] = "23.20";
char num2[] = "20.2";
printf("%.6lf", convertNumber(num1) + convertNumber(num2));
}

print float up to four place on either side

I am newbie, I am trying to print an float value upto four place on either side. For example 11.3 will be 0011.3000. For this I am using following line:-
float t = 11.3;
printf("%4.4f", t);
But I am getting 11.3000. So, is it even possible what i am trying to do? If yes then how? Thanks
The type of f is incorrect in your code fragment, it should be float or double.
To produce leading zeroes, use the 0 printf modifier and specify the minimum width expected, 9 characters in your example (4 places before the . plus the . plus 4 more places after the .).
The format is therefore %09.4f.
Here is the code:
#include <stdio.h>
int main() {
double t = 11.3;
printf("%09.4f\n", t);
return 0;
}
Output:
0001.3000
Note however that if the number is negative, you will only get 3 places before the . and if the number is too large in absolute value (<= -999.99995 or >= 9999.99995), the output will have more than 9 characters. If you mean to have 4 places before the . for negative values too, you should use % 010.4f: the number will then be prefixed with a space if positive and a - if negative:
#include <stdio.h>
int main() {
double t = 11.3;
printf("%09.4f\n", t);
printf("% 010.4f\n", t);
printf("% 010.4f\n", -t);
return 0;
}
Output:
0011.3000
0011.3000
-0011.3000
float t = 11.3;
printf("%4.4f", t);
In your code above 4 before . means total number of characters to be printed.
and 4 after . mean number of characters after decimal.
Since you want xxxx.xxxx hence you should write it like:
printf("%9.4f", t);
The first part of the format spec is the width of the field you are printing in, not the number of digits before the decimal place. Your desired output has 9 characters in it, zero padded on the left, so do
float t = 11.3;
printf("%09.4f", t);
This might break down if for example the integer part of your number gets too big For a finer level of control, work with integers:
float t = 11.3;
int i, f;
i = (int)t;
f = (int)((t - i) * 10000 + 0.5);
printf("%04d.%04d", i, f);
All this assumes positive numbers. Neither example shown here will work properly with negatives.

C print first million Fibonacci numbers

I am trying to write C code which will print the first 1million Fibonacci numbers.
UPDATE: The actual problem is I want to get the last 10 digits of F(1,000,000)
I understand how the sequence works and how to write the code to achieve that however as F(1,000,000) is very large I am struggling to find a way to represent it.
This is code I am using:
#include<stdio.h>
int main()
{
unsigned long long n, first = 0, second = 1, next, c;
printf("Enter the number of terms\n");
scanf("%d",&n);
printf("First %d terms of Fibonacci series are :-\n",n);
for ( c = 0 ; c < n ; c++ )
{
if ( c <= 1 )
next = c;
else
{
next = first + second;
first = second;
second = next;
}
printf("%d\n",next);
}
return 0;
}
I am using long long to try and make sure there are enough bits to store the number.
This is the output for the first 100 numbers:
First 100 terms of Fibonacci series are :-
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657
46368
75025
121393
196418
317811
514229
832040
1346269
2178309
3524578
5702887
9227465
14930352
24157817
39088169
63245986
102334155
165580141
267914296
433494437
701408733
1134903170
1836311903
-1323752223
512559680
-811192543
-298632863
-1109825406
-1408458269
...
Truncated the output but you can see the problem, I believe the size of the number generated is causing the value to overflow to negative. I don't understand how to stop it in all honesty.
Can anybody point me in the right direction to how to actually handle numbers of this size?
I haven't tried to print the first million because if it fails on printing F(100) there isn't much hope of it printing F(1,000,000).
You want the last 10 digits of Fib(1000000). Read much more about Fibonacci numbers (and read twice).
Without thinking much, you could use some bignum library like GMPlib. You would loop to compute Fib(1000000) using a few mpz_t bigint variables (you certainly don't need an array of a million mpz_t, but less mpz_t variables than you have fingers in your hand). Of course, you won't print all the fibonacci numbers, only the last 1000000th one (so a cheap laptop today has enough memory, and would spit that number in less than an hour). As John Coleman answered it has about 200K digits (i.e. 2500 lines of 80 digits each).
(BTW, when thinking of a program producing some big output, you'll better guess-estimate the typical size of that output and the typical time to get it; if it does not fit in your desktop room -or your desktop computer-, you have a problem, perhaps an economical one: you need to buy more computing resources)
Notice that efficient bignum arithmetic is a hard subject. Clever algorithms exist for bignum arithmetic which are much more efficient than the naive one you would imagine.
Actually, you don't need any bigints. Read some math textbook about modular arithmetic. The modulus of a sum (or a product) is congruent to the sum (resp. the product) of the modulus. Use that property. A 10 digits integer fits in a 64 bits int64_t so with some thinking you don't need any bignum library.
(I guess that with slightly more thinking, you don't need any computer or any C program to compute that. A cheap calculator, a pencil and a paper should be enough, and probably the calculator is not needed at all.)
The lesson to learn when programming (or when solving math exercises) is to think about the problem and try to reformulate the question before starting coding. J.Pitrat (an Artificial Intelligence pioneer in France, now retired, but still working on his computer) has several interesting blog entries related to that: Is it possible to define a problem?, When Donald and Gerald meet Robert, etc.
Understanding and thinking about the problem (and sub-problems too!) is an interesting part of software development. If you work on software developement, you'll be first asked to solve real-world problems (e.g. make a selling website, or an autonomous vacuum cleaner) and you'll need to think to transform that problem into something which is codable on a computer. Be patient, you'll need ten years to learn programming.
To "get the last 10 digits of F(1,000,000)", simply apply the remainder function % when calculating next and use the correct format specifier: "%llu".
There is no need to sum digits more significant than the 10 least significant digits.
// scanf("%d",&n);
scanf("%llu",&n);
...
{
// next = first + second;
next = (first + second) % 10000000000;
first = second;
second = next;
}
// printf("%d\n",next);
printf("%010llu\n",next);
My output (x'ed the last 5 digits to not give-away the final answer)
66843xxxxx
By Binet's Formula the nth Fibonacci Number is approximately the golden ratio (roughly 1.618) raised to the power n and then divided by the square root of 5. A simple use of logarithms shows that the millionth Fibonacci number thus has over 200,000 digits. The average length of one of the first million Fibonacci numbers is thus over 100,000 = 10^5. You are thus trying to print 10^11 = 100 billion digits. I think that you will need more than a big int library to do that.
On the other hand -- if you want to simply compute the millionth number, you can do so -- though it would be better to use a method which doesn't compute all of the intermediate numbers (as simply computing rather than printing them all would still be infeasible for large enough n). It is well known (see this) that the nth Fibonacci number is one of the 4 entries of the nth power of the matrix [[1,1],[1,0]]. If you use exponentiation by squaring (which works for matrix powers as well since matrix multiplication is associative) together with a good big int library -- it becomes perfectly feasible to compute the millionth Fibonacci number.
[On Further Edit]: Here is a Python program to compute very large Fibonacci numbers, modified to now accept an optional modulus. Under the hood it is using a good C bignum library.
def mmult(A,B,m = False):
#assumes A,B are 2x2 matrices
#m is an optional modulus
a = A[0][0]*B[0][0] + A[0][1]*B[1][0]
b = A[0][0]*B[0][1] + A[0][1]*B[1][1]
c = A[1][0]*B[0][0] + A[1][1]*B[1][0]
d = A[1][0]*B[0][1] + A[1][1]*B[1][1]
if m:
return [[a%m,b%m],[c%m,d%m]]
else:
return [[a,b],[c,d]]
def mpow(A,n,m = False):
#assumes A is 2x2
if n == 0:
return [[1,0],[0,1]]
elif n == 1: return [row[:] for row in A] #copy A
else:
d,r = divmod(n,2)
B = mpow(A,d,m)
B = mmult(B,B,m)
if r > 0:
B = mmult(B,A,m)
return B
def Fib(n,m = False):
Q = [[1,1],[1,0]]
return mpow(Q,n,m)[0][1]
n = Fib(999999)
print(len(str(n)))
print(n % 10**10)
googol = 10**100
print(Fib(googol, googol))
Output (with added whitespace):
208988
6684390626
3239047153240982923932796604356740872797698500591032259930505954326207529447856359183788299560546875
Note that what you call the millionth Fibonacci number, I call the 999,999th -- since it is more standard to start with 1 as the first Fibonacci number (and call 0 the 0th if you want to count it as a Fibonacci number). The first output number confirms that there are over 200,000 digits in the number and the second gives the last 10 digits (which is no longer a mystery). The final number is the last 100 digits of the googolth Fibonacci number -- computed in a small fraction of a second. I haven't been able to do a googolplex yet :)
This question comes without doubt from some programming competition, and you have to read these questions carefully.
The 1 millionth Fibonacci number is HUGE. Probably about 200,000 digits or so. Printing the first 1,000,000 Fibonacci number will kill a whole forest of trees. But read carefully: Nobody asks you for the 1 millionth Fibonacci number. You are asked for the last ten digits of that number.
So if you have the last 10 digits of Fib(n-2) and of Fib(n-1), how can you find the last 10 digits of Fib(n)? How do you calculate the last ten digits of a Fibonacci number without calculating the number itself?
PS. You can't print long long numbers with %d. Use %lld.
Your algorithm is actually correct. Since you're using unsigned long long, you have enough digits to capture the last 10 digits and the nature of unsigned overflow functions as modulo arithmetic, so you'll get the correct results for at least the last 10 digits.
The problem is in the format specifier you're using for the output:
printf("%d\n",next);
The %d format specifier expects an int, but you're passing an unsigned long long. Using the wrong format specifier invokes undefined behavior.
What's most likely happening in this particular case is that printf is picking up the low-order 4 bytes of next (as your system seems to be little endian) and interpreting them as a signed int. This ends up displaying the correct values for roughly the first 60 numbers or so, but incorrect ones after that.
Use the correct format specifier, and you'll get the correct results:
printf("%llu\n",next);
You also need to do the same when reading / printing n:
scanf("%llu",&n);
printf("First %llu terms of Fibonacci series are :-\n",n);
Here's the output of numbers 45-60:
701408733
1134903170
1836311903
2971215073
4807526976
7778742049
12586269025
20365011074
32951280099
53316291173
86267571272
139583862445
225851433717
365435296162
591286729879
956722026041
You can print Fibonacci(1,000,000) in C, it takes about 50 lines, a minute and no library :
Some headers are required :
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE (16 * 3 * 263)
#define BUFFERED_BASE (1LL << 55)
struct buffer {
size_t index;
long long int data[BUFFER_SIZE];
};
Some functions too :
void init_buffer(struct buffer * buffer, long long int n){
buffer->index = BUFFER_SIZE ;
for(;n; buffer->data[--buffer->index] = n % BUFFERED_BASE, n /= BUFFERED_BASE);
}
void fly_add_buffer(struct buffer *buffer, const struct buffer *client) {
long long int a = 0;
size_t i = (BUFFER_SIZE - 1);
for (; i >= client->index; --i)
(a = (buffer->data[i] = (buffer->data[i] + client->data[i] + a)) > (BUFFERED_BASE - 1)) && (buffer->data[i] -= BUFFERED_BASE);
for (; a; buffer->data[i] = (buffer->data[i] + a), (a = buffer->data[i] > (BUFFERED_BASE - 1)) ? buffer->data[i] -= BUFFERED_BASE : 0, --i);
if (++i < buffer->index) buffer->index = i;
}
A base converter is used to format the output in base 10 :
#include "string.h"
// you must free the returned string after usage
static char *to_string_buffer(const struct buffer * buffer, const int base_out) {
static const char *alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
size_t a, b, c = 1, d;
char *s = malloc(c + 1);
strcpy(s, "0");
for (size_t i = buffer->index; i < BUFFER_SIZE; ++i) {
for (a = buffer->data[i], b = c; b;) {
d = ((char *) memchr(alphabet, s[--b], base_out) - alphabet) * BUFFERED_BASE + a;
s[b] = alphabet[d % base_out];
a = d / base_out;
}
while (a) {
s = realloc(s, ++c + 1);
memmove(s + 1, s, c);
*s = alphabet[a % base_out];
a /= base_out;
}
}
return s;
}
Example usage :
#include <sys/time.h>
double microtime() {
struct timeval time;
gettimeofday(&time, 0);
return (double) time.tv_sec + (double) time.tv_usec / 1e6;
}
int main(void){
double a = microtime();
// memory for the 3 numbers is allocated on the stack.
struct buffer number_1 = {0}, number_2 = {0}, number_3 = {0};
init_buffer(&number_1, 0);
init_buffer(&number_2, 1);
for (int i = 0; i < 1000000; ++i) {
number_3 = number_1;
fly_add_buffer(&number_1, &number_2);
number_2 = number_3;
}
char * str = to_string_buffer(&number_1, 10); // output in base 10
puts(str);
free(str);
printf("took %gs\n", microtime() - a);
}
Example output :
The 1000000th Fibonacci number is :
19532821287077577316320149475 ... 03368468430171989341156899652
took 30s including 15s of base 2^55 to base 10 conversion.
Also it's using a nice but slow base converter.
Thank You.

odd numbers in language C? pb 'ram or algorithm'!

This program gives us the position of the odd numbers in a given integer, this program works well, but when I give him an integer in its numbers are greater than 10 -like 123456789123-, it doesn't work.
I do not know if is a problem of ram or algorithm ?
#include<stdio.h>
#include<stdlib.h>
main(){
int a,b;
int i = 0;
scanf("%d",&a);
while(a/10!=0){
b=a%10;
if(b%2!=0)
printf("\nodd number position: %d",i);
a=a/10;
i++;
}
if(a%2!=0)
printf("\nodd number position: %d",i);
system("pause");
}
The problem is one of processor (architecture) rather than RAM. On your platform the size of an int seems to be 32 bits which cannot hold a number as large as 123456789123. As Groo commented to Raon, you could use a string instead (if you don't plan to do any calculations on the number):
char a[1024] = {0}; /* should be plenty, but extend the array even more if needed */
fgets(a, sizeof a, stdin); /* fgets is recommended as it doesn't overflow */
int i, length = strlen(a);
for(i = 0; i < length; i++){
/* count your odd digits here
left as an exercise to the reader */
/* note that you must access the individual digits using a[i] */
}
Every data type is limited to specific range.for example char is limited to range -128 to 128. if you use the beyond this range. You might get unexpected results.
In your program if you give any number which is beyond the range of integer, then you will get unexpected results
if your int size is 4 byte/32-bit you can give input with in this range –2,147,483,648 to 2,147,483,647
if Your int size is 2 byte/16-bit you can give input with in this range –32,768 to 32,767
Check this Data Type Ranges.
And if you want to give large Numbers You can declare variable as long int/long long int
and don't forgot to change format specifier when using long int(%ld) and long long int(%lld)
You can also use string and check whether all characters are digits are not by using isdigit() function in ctype.h header and convert character digit into integer digit by substracting '0'(character zero). and check whether is that odd or not.
The problem is that 123456789123 exceed the storage limit for an integer data type,
try using a string to store the value and parse it, something like
#include<stdio.h>
int main(){
char a[] = "12345678912345678913246798";
int i = 0;
for (i=0; a[i] != '\0'; i++){
if ( a[i] % 2 != 0 ) printf("%c is odd\n", a[i]);
}
return 0;
}
#include<stdio.h>
void main() {
int i;
char s[256];
scanf("%s",s);
for( i=0; s[i]!=0; ++i ) {
/*int digit = s[i]-48;
if( digit%2==1 ) break;
- or even shorter: */
if( s[i]%2==1 ) break;
}
if( s[i]!=0 )
printf( "First odd digit position: %d", i );
else
printf( "All digits are even" );
}
Here is working sample: http://cfiddle.net/sempyi
I think this program will not give proper answer if you give more than 10 digits! please correct me if I am wrong.
The max Unsigned integer value is 4294967295 (in any 32 bit processor). if the given value is more than that then it will either limit to that max value or overflow will happen. So if you give a integer which is more than 4294967295 it will not work as it supposed to.
try printing the input. In that case you will know whether complete number is sent or Max number is sent to find the odd number's position.
One way to make it work is read the input number as array of characters and then try to figure out the odd number position.
Note: for signed integer maximum is 2147483647
123456789123 is 0x1CBE991A83
so if int is 32 bit, your number is truncated (to 3197704835 or 0xBE991A83).
Number you are giving input is greater than range of int. You need to change the data type Below link should help you.
http://www.tutorialspoint.com/ansi_c/c_basic_datatypes.htm
You need to choose a data type that matches the expected data range.
If you want your program to work for any number it is probably best to read the number one character at a time.
Code (not that in this code, position is counted with the most significant digit = 1, which is the other direction compared to your code):
int c;
unsigned long long pos = 0;
while (++pos) {
c = getc();
if (c < '0' || c > '9') break; // Not a digit
if ((c - '0')%2 != 0) {
printf("\nodd number position: %ulld", pos);
}
}
The code can handle numbers that have a ridiculus amount of digits. Eventually the pos variable will overflow, though.

Resources