I am writing a very basic program to print the range of an unsigned long long variable in C language (0 to ((2 ^ n) - 1) where n is the number of bits for the data type in any system (with C installed in it and according to the compiler). In my system, the size of a long long variable is 8 bytes.
I am using the following code:
#include<stdio.h>
#include<math.h>
int main()
{
unsigned long long n;
//n = pow(2, 63);
//n = (n * 2) - 1;
n = pow(2, 64) - 1;
printf("\nn: %llu\n", n);
return 0;
}
upon compiling, gcc gives me the following error:
Print_long_long_int.c:10:2: warning: overflow in implicit constant conversion [-Woverflow].
On executing it, I get the correct output of
n: 18446744073709551615
But, if I remove the single comments from the lines, and use them:
n = pow(2, 63);
n = (n * 2) - 1;
Instead of:
n = pow(2, 64) - 1;
It doesn't give me any such warning. And executes normally.
Why is this discrepancy happening?
Thanks!
When you are giving
pow(2,64) -1 ;
It exceeds the limit of unsigned long long. This is the reason you are getting that warning.
Range of unsigned long is 0 to 18,446,744,073,709,551,615
Result of pow(2,64) is 18446744073709551616.
Power should return an integer, and you're getting an unsigned long long. I just made a simple power function to handle unsigned long longs.
#include<stdio.h>
unsigned long long power(int base, int exponent)
{
unsigned long long n = 1;
int i;
for (i = 0; i < exponent ; i++)
n *= base;
return n;
}
int main()
{
unsigned long long n = power(2, 64) - 1;
printf("n: %llu\n", n);
return 0;
}
Related
This is a Luhn algorithm code and it works fine in an online complier but when I use it in my local vscode it is only giving 63 as output.
I dont know if its a memory issue as it late long variable.
i.e credit card number as input.
#include <stdio.h>
// Finds its Luhn algorithm to see if its a valid credit card number.
void checksum(long num)
{
int sum = 0;
for (int i = 0; num != 0; num /= 10, i++)
{
if (i % 2 == 0)
{
sum = sum + num % 10;
}
else
{
int digit = 2 * (num % 10);
sum = sum + (digit / 10) + (digit % 10);
}
}
printf("%d", sum);
}
int main()
{
long int num;
// Takes credit Card number as input.
do
{
printf("Number: ");
scanf("%li", &num);
} while (num < 0);
checksum(num);
return 0;
}
My inputs are like 374245455400126,378282246310005.
And output is always 63.
The result depends on the size of the type long int that can be equal either to the size of the type int or to the size of the type long long int.
So use the type long long int instead of the type long int.
Also as the program expects an unsigned value then instead of the signed type long long int it is even better to use the type unsigned long long int.
I am trying to make a function that quickly calculates x^y mod z. It works well when calculating something like 2^63 mod 3, but at 2^64 mod 3 and higher exponents it just returns 0.
I am suspecting an overflow somewhere, but I can't pin it down. I have tried explicit casts at the places where calculations (* and mod) are made, I have also made my storage variables (resPow, curPow) unsigned long long int (as Suggested here) but that didn't help much.
typedef unsigned long int lint;
lint fastpow(lint nBase, lint nExp, lint nMod) {
int lastTrueBit = 0;
unsigned long long int resPow = 1ULL;
unsigned long long int curPow = nBase;
for (int i = 0; i < 32; i++) {
int currentBit = getBit(nExp, i);
if (currentBit == 1) {
for (lint j = 0; j < i - lastTrueBit; j++) {
curPow = curPow * curPow;
}
resPow =resPow * curPow;
lastTrueBit = i;
}
}
return resPow % nMod;
}
I am suspecting an overflow somewhere,
Yes, both curPow * curPow and resPow * curPow may mathematically overflow.
The usual way to contain overflow here is to perform mod on intermediate products.
// curPow = curPow * curPow;
curPow = (curPow * curPow) % nMod;
// resPow =resPow * curPow;
resPow = (resPow * curPow) % nMod;
This is sufficient when nMod < ULLONG_MAX/(nMod - 1). (The mod value is half the precision of unsigned long long). Otherwise more extreme measures are needed as in: Modular exponentiation without range restriction.
Minor stuff
for(int i = 0; i < 32; i++) assumes lint/unsigned long is 32 bits. Portable code would avoid that magic number. unsigned long is 64-bits on various platforms.
LL is not needed here. U remains useful to quiet various compiler warnings.
// unsigned long long int resPow = 1ULL;
unsigned long long int resPow = 1U;
I have two functions here that together compute the nCr:
int factorial(int n) {
int c;
int result = 1;
for (c = 1; c <= n; c++)
{
result = result*c;
}
return result;
}
int nCr(int n, int r) {
int result;
result = factorial(n)/(factorial(r)*factorial(n-r));
return result;
}
I am having trouble with an error check I need to implement. As n gets larger, I won't have the ability to computer n! and this error check has to exist in both nCr and factorial. They both must detect this overflow.
Currently, when I enter a number that is too large for computation, I get a floating type error returned from the command line.
I am having trouble accounting for this overflow check. Any help would be much appreciated, thanks.
A better way of calculating binomial coefficients
typedef unsigned long long ull;
ull nCr(int n, int r) {
ull res = 1;
if (r > n - r) r = n - r;
for (int i = 0; i < r; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
In your code, the maximum value is always factorial(n),
so you only need to check that n! isn't bigger than 2.147.483.647 (max int value).
Please note that the stored max value can be different based on the size of the int type in memory (different machines can specify different sizes).
However, the last bit in int type variables is reserved for storing the sign (+ or -), thus the max value can be half of 65.535 and 4.294.967.295 i.e. 32.767 and 2.147.483.647 for int types.
SIZE_OF_INT(bits) MAX VALUE(UNSIGNED) MAX_VALUE(SIGNED)
---------------------------------------------------------------
16 65.535 32.767
32 4.294.967.295 2.147.483.647
The value of 13! can go beyond the max value of the int type (in 32 bit).
12! = 479.001.600 and
13! = 6.227.020.800
So, you need to check in nCr(int n, int r) that the max value of n is always less than 13 (i.e. n<=12) and r<=n.
And in factorial(int n): n<=12.
The nth term of the series is f(n).
f(n) = 1, when n=1
f(n)= ((n-1)*(8*(n–2)* 2+ 20)+4) , when n>1
P(n)=f(1)+f(2)+.....f(n)
1<=n<=10^9
for a given n we have to find P(n) modulo 10^9+7.
I solved the equation and finally getting the answer as
P(n)=(16n^3-18n^2+14n-12)/3
Problem comes when I implemented it in c++.
Given below the code tell me whats wrong with it and how to resolve it?
#include<stdio.h>
#define c 1000000007
int main()
{
long long int t,n,sum;
scanf("%lld",&t);
while(t--)
{
sum=0;
scanf("%lld",&n);
if(n==1)
printf("1\n");
else
{
sum=(((16*(((((n%c)*(n%c))%c)*(n%c))%c)%c)+14*(n%c))%c-(18*(((n%c)*(n%c))%c)%c+12)%c)/3;
sum++;
printf("%lld\n",sum);
}
}
return 0;
}
There are multiple issues in your code.
Problem 1:
An expression like long long b = ((a%c)*(a%c))%c; with a and b being long long
and c just a "plain number", ie. int, is still subject to int overflow, without
using the full capabilities of long long. The reason is the result of modulo:
long long = ((long long % int) * (long long % int)) % int;
long long = (int * int) % int;
long long = int % int; //overflow here
long long = int;
long long = long long; //expanding too late
//finished
As an example to check (http://ideone.com/kIyM7K):
#include <iostream>
using namespace std;
int main() {
int i = 1000000;
long long ll = 1000000;
cout<< ((999999%i)*(999999%i)*(999999%i)) << endl;
cout<< ((999999%ll)*(999999%ll)*(999999%ll)) << endl;
return 0;
}
In your code, 1000000007 is not a long long ...
Use 1000000007ULL to treat is as unsigned long long
Problem 2:
You´re using (or at least "used", before the edits) %lld in printf and scanf
for unsigned long long, which is %llu. %lld would be a signed long long
Problem 3:
P(n) purely mathematical and without modulo is positive for every natural number n>=1.
But P(0) is negative, and more important: The four parts of your equation modul´t
and the added/subtracted together could result in a negative number, which is congruent
to the positive expected result, but C doesn´t know that.
So, use signed instead of unsigned, and after the whole calculation, check
if the result is <0 and add c to it to make it >0
Problem 4:
A problem with parenthesis and operator precedence somewhere in your long formula.
A working example, but without the loops and input:
#include<stdio.h>
int main()
{
signed long long n, res, c;
n = 2456ULL;
c = 1000000007ULL;
signed long long part1 = (16*(((n%c)*(n%c)%c)*(n%c)%c))%c;
signed long long part2 = (18*((n%c)*(n%c)%c))%c;
signed long long part3 = (14*(n%c))%c;
res = ((part1 - part2 + part3 - 12)%c)/3 + 1;
printf("%lld\n", res);
return 0;
}
Not a problem:
You don´t need a special check for n=1, because the
whole calculation will result in 1 anyways.
I'm writing C code that converts from an integer to its binary representation, reverses the binary and then converts back to an integer. It's working well, but I need it to work for input values up to 10^9. Right now, it seems to break for anything larger than 10^7. What I mean is I put in a number such as 10000000 and get out 17967657062982931584 as being the binary representation (despite being accurate for smaller integers). In addition, I am not sure where my int_to_binary is the only function experiencing this problem, or if the others need to be optimized for large inputs as well. Any ideas where I'm going wrong? Thank you.
#include <stdio.h>
#include <string.h>
unsigned long long int_to_binary(unsigned long long k) {
if (k == 0) return 0;
if (k == 1) return 1;
return (k % 2) + 10 * int_to_binary(k/2);
}
unsigned long long reverse_int(unsigned long long l) {
unsigned long long reversed;
reversed = 0;
while (l > 0) {
reversed = reversed * 10 + (l%10);
l = l / 10;
}
return reversed;
}
unsigned long long binary_to_int(unsigned long long k) {
char binaryString[80];
snprintf(binaryString, 4, "%llu", k);
unsigned long long decimal = 0;
int length = strlen(binaryString);
int i = 0;
while(i < length) {
decimal = (decimal << 1) + (binaryString[i] - 0x30);
i++;
}
return decimal;
}
int main() {
int number;
printf("Enter a number: ");
scanf("%d", &number);
printf("You entered %d\n", number);
unsigned long long b = int_to_binary(number);
printf("In Binary, this is %llu\n", b);
unsigned long long c = reverse_int(b);
printf("When we reverse it, it looks like this: %llu\n", c);
unsigned long long d = binary_to_int(c);
printf("And when we convert that back to an int, it looks like this: %llu\n", d);
return 0;
}
You're using long long to represent a binary number as a decimal. On many architectures this results in the maximum value being stored of 2**64-1 = 18446744073709551615.
If you put in a decimal number such as 10000000, it cannot be represented as a decimal-binary number in 64 bits.
The problem is attempting to manipulate a binary number as a sum of powers of ten. It's more efficient to manipulate binary directly. Just change 10 to 2 in the reverse_int function.
unsigned long long reverse_int(unsigned long long l) {
unsigned long long reversed;
reversed = 0;
while (l > 0) {
reversed = reversed * 2 + (l%2);
l = l / 2;
}
return reversed;
}
In order to print numbers in binary, write a loop, testing each bit in sequence, using modulo % or bitwise operators like & and >>.