Parsing a number with more than 10 digits in C - c

I'm trying to calculate UPC codes using C as a language, but I'm now having a problem with the precision. I tried int, float, long long, etc.
Here's the code:
#include <stdio.h>
int main(void)
{
float upc;
printf("Enter UPC:\n");
scanf ("%d", &upc);
printf("upc = %f ", upc);
}
the results are :
Enter UPC code:
123456789012
upc = 123456790528.000000 d= 1
Process returned 30 (0x1E) execution time : 6.672 s
Press any key to continue.
How can I show the number as is? It's only 12 digits.
I'm using CodeBlocks, is there an IDE that can handle this better?
Note: please don't tell me to just use char! I want to make some calculations later.

Universal product codes are not subject to integer arithmetic operations, so it doesn't entirely make sense to represent them using int. Each digit is assigned a particular meaning, so a string makes more sense.
If you really just want a band-aid, uint64_t from <stdint.h> will always be able to hold a 12-digit number. Do not use a floating-point type, though, as they are not designed to hold exact integers, but rather to approximate real numbers.
The correct way to use uint64_t with printf and scanf is with the fixed-width format specifiers from <inttypes.h>:
scanf ( "%" SCNd64, &upc);
printf("upc = %" PRId64 "\n", upc);

A float can typically store just 6-7 decimal digits. A 32-bit int can store 9 digits (10 if the leading digits is 3 or less). To store a 12-digit integer, you need to use either a long long (up to 18 digits) or perhaps a double (up to 15-16 digits), though a double is less desirable.
Hence:
#include <stdio.h>
int main(void)
{
long long upc;
printf("Enter UPC:\n");
scanf ("%lld", &upc);
printf("upc = %lld\n", upc);
return(0);
}

Actually can you be more clear of what you want as your output? I suggest you one modification in to use long long int instead of float.

Related

C Program to Print an Integer (Entered by the User) Wrong Output Coming When The number is BIG [duplicate]

This question already has answers here:
Why are the array elements changed after sort,C
(2 answers)
Closed 4 years ago.
Here is my code for the program.
#include <stdio.h>
int main() {
int number;
printf("Enter an integer: ");
scanf("%d", &number);
printf("You entered: %d", number);
return 0;
}
If I enter an integer: 12345678912345678
Result is Showing: 1578423886
Why is this happening ?
The problem is that on the system you're running on, int is not large enough to store integers as large as you're trying to enter (the limit is architecture-specific, and can be checked via INT_MAX). If you define your variable as a long long instead, it will be able to hold larger values (long long is 64 bits on most common architectures), and so:
#include <stdio.h>
int main() {
long long number;
printf("Enter an integer: ");
scanf("%lld", &number);
printf("You entered: %lld", number);
return 0;
}
outputs:
Enter an integer: 12345678912345678
You entered: 12345678912345678
That happens because data types on any programming language have limits, so you cannot simply put any number into an integer data type. Probably for your test the limit is 2.147.483.647 for integer data type, if you want to receive a bigger number you will have to switch to long or maybe unsigned long, it all depends of your needs, and when it comes to handle really really big numbers probably you will need to read it as string and then parse it to a special structure or class than can handle that really big number.
This is happening because On a system if the value won't fit in an int, then the result of the conversion is implementation-defined. (Or, starting in C99, it can raise an implementation-defined signal, but I don't know of any compilers that actually do that.) What typically happens is that the high-order bits are discarded, but you shouldn't depend on that. (The rules are different for unsigned types; the result of converting a signed or unsigned integer to an unsigned type is well defined.)
Because of this discarding you get result like mention in comment 12345678912345678 is a 54-bit number. In hex it's 0x2bdc545e14d64e. Interestingly enough 1578423886 is 0x5e14d64e(lower bits are same and higher are discarded)

create number 0 only using int in the C

#include <stdio.h>
struct real_num
{
int int_num;
int frac_num;
};
void main()
{
struct real_num num1;
printf("input the number : ");
scanf("%d.%d",&num1.int_num,&num1.frac_num):
printf("%d.%d",num1.int_num,num1.frac_num);
}
i input 12.012 but buffer save 12.12 i want a 012 but this buffer save 12
what should i do? i want a save 012 (using only int)
Numbers are a matter of arithmetic. 1, 01, 1.0, 1.000, 0x01, 1e0 all describe the same number: whichever representation you use has the same mathematical properties, and behaves identically in calculation (ignoring the matter of computer storage of numbers as int or float or double... which is again another matter entirely).
The representation of a number is a matter of sequences of characters, or strings. Representations of numbers can be formatted differently, and can be in different bases, but can't be calculated with directly by a computer. To store leading zeroes, you need a string, not an int.
You typically convert from number representation to number at input, and from number to number representation at output. You would achieve your stated desire by not converting from number representation to number at input, but leaving it as a string.
You don't want to store 012, you want to store 0.012.
The value 0.012 in binary is (approximately):
0.00000011000100100110111010010111b
..and the value 12.012 is (approximately):
110.00000011000100100110111010010111b
Note that 0.012 is impossible to store precisely in binary because it would consume an infinite number of bits; in the same way that 1/3 can't be written precisely in decimal (0.333333333.....) because you'd need an infinite number of digits.
Let's look at 12.012. In hex it's this:
0x0000000C.03126E97
This makes it easier to see how the number would be stored in a pair of 32-bit integers. The integer part in one 32-bit integer, and the fractional part in another 32-bit integer.
The first problem is that you're using signed 32-bit integers, which means that one of the bits of the fraction is wasted for a sign bit. Essentially, you're using a "sign + 31 bit integer + wasted bit + 31 bit fraction" fixed point format. It'd be easier and better to use an unsigned integer for the fractional bits.
The second problem is that standard C functions don't support fixed point formats. This means that you either have to write your own "string to fixed point" and "fixed point to string" conversion routines, or you have use C's floating point conversion routines and write your own "floating point to fixed point" and "fixed point to floating point" conversion routines.
Note that the latter is harder (floating point is messy), slower, and less precise (double floating point format only supports 53 bits of precision while you can store 62 bits of precision).
A fraction does not consists of a single integer. A fraction consists of 2 integers: numerator/denominator.
Code needs to keep track of width of the fraction input. Could use "%n" to record offset in scan.
#include <stdio.h>
struct real_number {
int ipart;
int num;
int den_pow10;
};
void main(void) {
struct real_number num1;
printf("input the number : ");
fflush(stdout);
int n1 = 0;
int n2 = 0;
scanf("%d.%n%d%n",&num1.ipart, &n1, &num1.num , &n2):
if (n2 == 0) {
fprintf(stderr, "bad input\n");
return -1;
}
num1.den_pow10 = n2 - n1;
printf("%d.%*0d",num1.ipart,num1.den_pow10, num1.frac_num);
return 0;
}
Input/Output
input the number : 12.00056
Result 12.00056

Get printf to print all float digits

I'm confused about the behavior of printf("%f", M_PI). It prints out 3.141593, but M_PI is 3.14159265358979323846264338327950288. Why does printf do this, and how can I get it to print out the whole float. I'm aware of the %1.2f format specifiers, but if I use them then I get a bunch of unused 0s and the output is ugly. I want the entire precision of the float, but not anything extra.
Why does printf do this, and how can I get it to print out the whole
float.
By default, the printf() function takes precision of 6 for %f and %F format specifiers. From C11 (N1570) §7.21.6.1/p8 The fprintf function (emphasis mine going forward):
If the precision is missing, it is taken as 6; if the precision is
zero and the # flag is not specified, no decimal-point character
appears. If a decimal-point character appears, at least one digit
appears before it. The value is rounded to the appropriate number
of digits.
Thus call is just equivalent to:
printf("%.6f", M_PI);
The is nothing like "whole float", at least not directly as you think. The double objects are likely to be stored in binary IEEE-754 double precision representation. You can see the exact representation using %a or %A format specifier, that prints it as hexadecimal float. For instance:
printf("%a", M_PI);
outputs it as:
0x1.921fb54442d18p+1
which you can think as "whole float".
If all what you need is "longest decimal approximation", that makes sense, then use DBL_DIG from <float.h> header. C11 5.2.4.2.2/p11 Characteristics of floating types :
number of decimal digits, q, such that any floating-point number with
q decimal digits can be rounded into a floating-point number with p
radix b digits and back again without change to the q decimal digits
For instance:
printf("%.*f", DBL_DIG-1, M_PI);
may print:
3.14159265358979
You can use sprintf to print a float to a string with an overkill display precision and then use a function to trim 0s before passing the string to printf using %s to display it. Proof of concept:
#include <math.h>
#include <string.h>
#include <stdio.h>
void trim_zeros(char *x){
int i;
i = strlen(x)-1;
while(i > 0 && x[i] == '0') x[i--] = '\0';
}
int main(void){
char s1[100];
char s2[100];
sprintf(s1,"%1.20f",23.01);
sprintf(s2,"%1.20f",M_PI);
trim_zeros(s1);
trim_zeros(s2);
printf("s1 = %s, s2 = %s\n",s1,s2);
//vs:
printf("s1 = %1.20f, s2 = %1.20f\n",23.01,M_PI);
return 0;
}
Output:
s1 = 23.010000000000002, s2 = 3.1415926535897931
s1 = 23.01000000000000200000, s2 = 3.14159265358979310000
This illustrates that this approach probably isn't quite what you want. Rather than simply trimming zeros you might want to truncate if the number of consecutive zeros in the decimal part exceeds a certain length (which could be passed as a parameter to trim_zeros. Also — you might want to make sure that 23.0 displays as 23.0 rather than 23. (so maybe keep one zero after a decimal place). This is mostly proof of concept — if you are unhappy with printf use sprintf then massage the result.
Once a piece of text is converted to a float or double, "all" the digits is no longer a meaningful concept. There's no way for the computer to know, for example, that it converted "3.14" or "3.14000000000000000275", and they both happened to produce the same float. You'll simply have to pick the number of digits appropriate to your task, based on what you know about the precision of the numbers involved.
If you want to print as many digits as are likely to be distinctly represented by the format, floats are about 7 digits and doubles are about 15, but that's an approximation.

Reversing a 5 digit number gives negative number

This is my program for reversing a number.But when I take 5 digits as input, sometimes the answer is correct and positive and sometimes it's negative.
#include<dos.h>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
int main()
{
clrscr();
int a,b,c;
b=0;
printf("Enter the no");
scanf("%d",&a);
c=a;
while(a>0)
{
b=(b*10)+(a%10);
a=a/10;
}
printf("\noriginal no %d",c);
printf("\nreversed no is %d",b);
getch();
return 0;
}
If input: 12111
output: 11121
input: 22333
output: -32214
The limit of integer is from -32768 to 32767, then why is the answer negative?
I tried using long but I got my reversed number as 0.
It looks like this is a 16-bit DOS program? So your int is only 16 bits/2 bytes, and your program is overflowing it.
You could try detecting when this condition will happen, and/or use unsigned to avoid negative numbers or a long instead of int to store bigger values (though this program will still output incorrect answers if you overflow).
What's the overall aim? - Can you just doing it by reversing a string instead?
As Bathsheba mentioned, sizeof(int) is apparently 2, and given the headers you're using, the platform is MS-DOS, which means your int only has 16 bits of information available. Because the first bit is the sign bit, that leaves you with 15 bits and 2^15 is 32768, meaning your range is -32767..+32767. What you want is an unsigned int and %u for scanf and printf. That will allow you to use 0..65535.
Need to be able to handle all 5-digit numbers? Switch to long instead (it won't matter if you make it signed or unsigned other than using %ld or %lu for signed or unsigned respectively), and you will have -2147483648..+2147483647 (signed) or 0..4294967295 (unsigned), which will give you more than enough range for a 5-digit number.
If you have problems with using long and the format is correct for scanf and printf, the problem is in your logic and not your reading of numbers at least.
If the limit is 32767, then reversing 22333 would yield 33322, which is larger than the limit!!!
If you want to use long instead of int, then you should also use "%ld" instead of "%d".

Printing a very large whole number in C

I've stored a very large number in a float variable, but when I print it I want to only display the whole number part and nothing after the decimal point.
For numbers in the int or long range, I would do a casting but this hasn't helped me because the number I want to print is too long for int or long.
I've looked at this explanation: http://www.cprogramming.com/tutorial/printf-format-strings.html but I haven't succeeded in solving this.
this is my code and my attempt to do the casting:
double sum=552074001368;
long long_sum;
long_sum = (long)(sum); //int casting for double "add"
if(sum>=0) printf("=\n%ld\n",long_sum);
else printf("=\n%ld\n",-long_sum);
I don't want to use a specific precision like printf("%15f") because this variable fluctuates and is sometimes very short like 4 digits.
Use the precision modifier .0 and print the floor of the number:
printf("%.0f\n", floor(sum));
(Or the floor of the abs, if you want only the magnitude, as in your example code.)
I think what you're after is %.0f. For example:
#include <stdio.h>
int main(){
double x = 1234.567;
printf("%.0f", x);
return 0;
}
...prints:
1235
Why are you casting to long at all? Use the printf format specifiers to control what and how many characters are printed.
http://www.cplusplus.com/reference/clibrary/cstdio/printf/
Remember that both the width and the precision can be specified by a variable and doesn't have to be known at compile time:
printf("=\n%.*lf\n", 4, sum); // print 4 places behind the decimal point
int i;
i = 5;
// print only the whole number part of sum and output at least i characters,
// pad with leading spaces if number requires fewer than i characters
printf("=\n%*.*lf\n", i, 0, sum);
This line is problematic:
double sum=552074001368;
Since that is an integer literal, the compiler will first check if the number will fit in an int, then long, then long long. If it won't fit in long long I suspect you'll get either a compiler error or undefined behavior wrap-around, I'm not sure of which.
If your compiler supports long long, then the code will work and the number will be stored in a temporary long long (which will be optimized away). This long long is then stored inside a double.
Instead, write like this:
double sum=552074001368.0;
The .0 syntax gives you a double floating point literal without involving integer types at all.
double sum=552074001368LL;
long long long_sum;
long_sum = (long long)(sum);
if(sum>=0) printf("=\n%lld\n",long_sum);
else printf("=\n%lld\n",-long_sum);

Resources