C : erroneous output for "(long long int) = (long long int) * (double)"? - c

long long int A = 3289168178315264;
long long int B = 1470960727228416;
double D = sqrt(5);
long long int out = A + B*D;
printf("%lld",out);
This gives result : -2147483648
I am not able to figure out why (it should be a positive result).
Can somebody help?

maybe you have to specify those constants as "long long" literals? e.g. 3289168178315264LL

What compiler/operating system are you using? I ran your code using Visual C++ 2008 Express Edition on Windows XP and IT WORKS - answer: 6578336356630528 (this is a 53-bit number, so it just fits inside a double).
I also tried two variations to see if the order of operations mattered:
long long int out = A;
out+=B*D;
long long int out = B*D;
out+=A;
These both work as well!
Curious.

My guess is that the compiler needs to round the result from "A+B*D" to an integer first, because you're storing the result inside an int field. So basically, you're having a datatype conflict.
Both A and B are still valid numbers for a long long int, which is 8 bytes long. You could even multiply them by 1.000 and still have valid long long int values. In some other languages it's also known as the int64.
A double, however, is also 64-bits but part of those are used as exponent. When you multiply a double with an int64, the result would be another double. Adding another int64 to it still keeps it a double. Then you're assigning the result to an int64 again without using a specific rounding method. It would not surprise me if the compiler would use a 4-bit rounding function for this. Am even amazed that the compiler doesn't puke and break on that statement!
Anyways, when using large numbers like these, you have to be extra careful when mixing different types.

Your answer (have to verify) calcuates successfully, however, it causes an overflow into the sign bit, which makes the answer negative. Solution : make all your variables unsigned.
Why:
Numbers are stored as series of bits in you computer's memory. The first bit in such a series, when set means that you number is negative. So the calculation works, but overflows into the sign bit.
Recommendation:
If you're working with numbers this big, I recommend you to get a multiprecision arithmetic library. 'T will save you a lot of time and trouble.

The parameter to sqrt should be double.
#include <math.h>
double sqrt( double num );
And also we should explict cast the result from B * D to long long.
long long int A = 3289168178315264;
long long int B = 1470960727228416;
double D = sqrt(5.0);
printf("%f\n",D);
long long int out = A + (long long) (B * D);
printf("%lld",out);

Related

How to combine two numbers to get a long long integer?

I am trying to combine two large numbers together which would result making a "long long int". For example:
a = -1716642972;
b = 43828807;
z = a and b;
In this case, I want z to equal -171664297243828807.
I know most of you are thinking, "why on earth would you want to do that?". You'll just have to trust me when I say there is a reason for wanting to do this.
details to know:
Variable a is expected to be 10 digits so I will be defining it as a "long" integer. Just to be on the safe side. It can be either a negative or a positive number.
variable b will be the last 8 digits of the seconds value from the time function. This means there is a chance for variable b to equal, 00000000. The number will always be positive.
variable z will be a combination of variables a and b. It has to be a "long long int". Variable a will always be before variable b. If variable b equals 00000000, then I want that implemented in variable z: -171664297200000000 or -171664297200000001, etc...
I have tried setting "long long z" equal to (a*100000000)+b but I end up getting some crazy number. This also gives the warning of an overflow. I'm assuming this has to do with integer types. Any help will be appreciated. Thanks!
Simply doing (a*100000000)+b can overflow if a is not large enough to hold the resulting type. A long long is guaranteed to hold a signed 64-bit quantity, so cast a to that type before performing the calculation.
Also, if a is negative, then you'll first want to invert the sign of b before adding it.
long long z = (long long)a * 100000000 + (a>=0 ? b : -b);
What I ended up doing is using the following code:
long a = -1716642972;
int b = 43828807;
// combine a and b as a string. Be sure to specify variable types.
char string[20];
snprintf(string, 20, "%ld%i", a, b);
//convert the string into a long long (%lld)
long long z;
sscanf(concat, "%lld", &z);
While this may be a lengthier process, it got the job done. On the plus side, with this process I don't need to be picky with integer types, as long as I specify what those types are.
If this is an arrangement to handle timestamps with a precision of 1 part in 10^8, then the best is that you manage both quantities in a structure struct my_time as
struct my_time {
unsigned long mt_sec; /* 0..UINT_MAX */
unsigned int mt_tens_of_nanosec; /* 0..99999999 */
};
But IMHO you should better to use a inverse power of 2 to represent fractions of a second, as this only represents a tedious task to be converted to decimal (which is something you are going to do only when outputting or inputting to the computer, and never when doing calculations). This is, for example, how NTP describes its timestamps. If you decide to use NTP (A standard format in internet) I can give you a sample implementation stored in one of my git repositories. You can find it here (you will need to read the code to understand it, but it gives approx. 232 ps resolution with an epoch in jan 1st 1900)

What's the role of L in modulo 1000000007L?

When you're a total noob programming, a lot of things looks like magic,
so solving some classic problems at SPOJ using C language, I found one called DIAGONAL.
After some attempts I gave up and went searching for solutions and I found this one:
#include <stdio.h>
int main() {
int num_cases, i;
long long mod_by = 24*1000000007L;
scanf("%d", &num_cases);
long long n;
long long answer;
for(i = 0; i < num_cases; i++) {
scanf("%lld", &n);
long long x = (n*(n-1)) % (mod_by);
long long y = (x*(n-2)) % (mod_by);
long long z = (y*(n-3)) % (mod_by);
answer = z / 24;
printf("%lld\n", answer);
}
return 0;
}
At first glance I thought that L with the modulo was some kind of mistake made by the user who posted the code (haha who would mix numbers with letters this way?! nonsense! -thought the noob-), but when I fixed the (many) wrongs in my code and used this modulo, it didn't work without the magic L (I got Wrong Answer).
Then I substituted the L with the ASCII code number (because well, maybe it was that!) and it also didn't work.
Since then I'm trying to understand what is the logic behind this. How can I get the same results removing this L?
It's not like one just woke up in the morning and "uhm, maybe if I add this L it will work", but I just couldn't find other examples of this (random letter added to a large number for calculations) googling.
long long mod_by = 24*1000000007L; is a problem.
The L suffix insures the constant 1000000007 is at least of type long.1 Without the L, the type may have been int or long.
Yet since long may only be 32-bit, the ~36-bit product can readily overflow long math leading to undefined behavior (UB).
The assignment to a long long happens after and does not affect the type nor range of the multiplication.
Code should use LL to form the product and protect against overflow.
long long mod_by = 24LL*1000000007;
// or
long long mod_by = 24*1000000007LL;
In general, make certain the calculation occurs at least with the width of the destination.
See also Why write 1,000,000,000 as 1000*1000*1000 in C?.
1 In OP's case, apparently int is 32-bit and long is 64-bit so code "worked" with a L and failed without it. Yet porting this code to a 32-bit long implementation, code fails with or without an L. Insure long long math with an LL constant.
The L suffix when applied to an integer constant means the constant has type long.
This is done to prevent overflow when the value is multiplied by 24. Without the suffix, two constants of type int are multiplied giving an int result. Assuming 32 is 32 bits, the result will overflow the range of an int (231-1) causing undefined behavior.
By making the constant have type long, assuming a long is 64 bits, it allows the multiplication to be done using and type and therefore not cause overflow and give you the correct value.
L is a suffix that means that the number is of type long, otherwise it will default to type int that means the result of the operation 24 * 1000000007 will also be of type int.
As an int is usually 4 bytes in size the result will overflow, this happens before it being assigned to mod_by, and for that reason it invokes undefined behavior.
As the result of the arithmetic operation is converted to the larger type, e.g:
int * int = int
int * long = long
For the result of the operation to be of type long one of the operands must also be of type long.
Note that long is not guaranteed to have 8 bytes in size, the minimum allowed size for a long is 4 bytes, so you can invoke the same undefined behavior deppending on the platform where you compile your program.
Using LL for long long will be more portable.

How to convert some long double to long int in c?

I'm trying to convert a double type variable to a long long int. The only way I know to do it is by casting. Althoulg it seems ok, I'm not receiving the number I wanted.
I post the code piece bellow:
double fator = 100000000;
long long int iLongitude = (long long int)(fLongitude*10000000);
The number I expected was -4396478167 and I'm getting -439647816, without the last digit.
Thanks for the help!
It seems you just need to add one more zero, and also round:
(long long int)(fLongitude*100000000 + 0.5);
Since casting truncates results, the + 0.5 will round up if the fractional part is larger than 0.5.

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);

How to use % operator for float values in c

When I use % operator on float values I get error stating that "invalid operands to binary % (have ‘float’ and ‘double’)".I want to enter the integers value only but the numbers are very large(not in the range of int type)so to avoid the inconvenience I use float.Is there any way to use % operator on such large integer values????
You can use the fmod function from the standard math library. Its prototype is in the standard header <math.h>.
You're probably better off using long long, which has greater precision than double in most systems.
Note: If your numbers are bigger than a long long can hold, then fmod probably won't behave the way you want it to. In that case, your best bet is a bigint library, such as this one.
The % operator is only defined for integer type operands; you'll need to use the fmod* library functions for floating-point types:
#include <math.h>
double fmod(double x, double y);
float fmodf(float x, float y);
long double fmodl(long double x, long double y);
When I haven't had easy access to fmod or other libraries (for example, doing a quick Arduino sketch), I find that the following works well enough:
float someValue = 0.0;
// later...
// Since someValue = (someValue + 1) % 256 won't work for floats...
someValue += 1.0; // (or whatever increment you want to use)
while (someValue >= 256.0){
someValue -= 256.0;
}
consider : int 32 bit and long long int of 64 bits
Yes, %(modulo) operator isn't work with floats and double.. if you want to do the modulo operation on large number you can check long long int(64bits) might this help you.
still the range grater than 64 bits then in that case you need to store the data in .. string and do the modulo operation algorithmically.
or either you can go to any scripting language like python
If you want to use an int use long long, don't use a format that is non-ideal for your problem if a better format exists.

Resources