Calculation of higher values in C - c

The following code is not working properly. I wanted it to print the sum of 2 billion + 2 billion. Even though I'm using long here, I can't get the answer correct.
#include<stdio.h>
#include<stdlib.h>
int main(void){
long a = 2000000000;
long b = 2000000000;
printf("%li\n",a + b);
return 0;
}
When I run this program I get the value -294967296. I'm using VS Code IDE, Mingw compiler and windows version is windows 11.

long is at least 32-bit and its range must span at least +/- 231 - 1 or +/-2,147,483,647.
On some machines a long is wider such as [-263 ...
263 - 1].
On OP's machine, it is [-231 ... 231 - 1].
For OP. a + b inccurs signed integer overflow which in undefined behavior (UB) as the sum of two long is outside the long range. A common result is the sum is "wrapped" and results in a long of -294,967,296 although many other results are possible including code crash.
To handle sums like 4,000,000,000, perform the addition with unsigned long math with its minimum rage of [0 ... 232 - 1] or use long long.
// printf("%li\n",a + b);
printf("%lli\n",0LL + a + b);
Or ...
long long a = 2000000000;
long long b = 2000000000;
printf("%lli\n",a + b);

The size of long integer is not fixed unlike other data types. It varies from architectures, operating system and even with compiler that we are using. In some of the systems it behaves like an int data type or a long long data type as follows:
OS Architecture Size
Windows IA-32 4 bytes
Windows Intel® 64 or IA-64 4 bytes
Linux IA-32 4 bytes
Linux Intel® 64 or IA-64 8 bytes
Mac OS X IA-32 4 bytes
Mac OS X Intel® 64 or IA-64 8 bytes
long might be 32 bit in your case. To avoid this confusion, use stdint where you can be sure of the sizes and also portable
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<inttypes.h>
int main(void){
int64_t a = 2000000000;
int64_t b = 2000000000;
// printf("%lli\n",a + b);
printf("res = %" PRI64d "!\n", a+b);
return 0;
}

The max size of a long may be the same as an int, you should use long long instead.
Integer size in C

Related

Save 128 bit value (unsigned) when max data type has 64 bits

I have to save the number of non zero entries in a matrix with dimensions that could be
as big as uint64_t x uint64_t resulting in a 128 bit value.
Im not sure which data-type would be right for this variable in C as it would require 128 bits (unsigned).
I would use __int128 as a data type but my problem is that when I test the max. supported data type on my system with
#include <stdio.h>
#include <stdint.h>
int main() {
printf("maxUInt: %lu\n", sizeof(uintmax_t));
printf("maxInt: %lu", sizeof(intmax_t));
}
It gives the following result:
maxUInt: 8
maxInt: 8
meaning that 8 Bytes is the maximum for number representation.
So this is troubling me as the result is possibly 128 bits == 16 Bytes big.
Will __int128 still work in my case?
We're talking about the size of an array, so uintmax_t and intmax_t are irrelevant.
malloc() accepts a size_t. The following therefore computes the limit of how much you can request:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
printf( "2^( %zu * %d ) bytes\n", sizeof( size_t ), CHAR_BIT );
For me, that's 2^( 8 * 8 ) octets.
18,446,744,073,709,551,616
But I'm an an x86-64 machine. Those don't support nearly that much memory. The instruction set only supports 2^48 octets of memory.
281,474,976,710,656 (1/65,536 of what 64 bits can support)
But no x86-64 machine supports that much. Current hardware only supports 2^40 octets of memory.
1,099,511,627,776 (1/16,777,216 of what 64 bits can support)
So unless you have some very special hardware, 64 bits is more than enough to store the size of any array your machine can handle.
Still, let's answer your question about support for __int128 and unsigned __int128. These two types, if supported, are an extension to the standard. And they are apparently not candidates for intmax_t and uintmax_t, at least on my compiler. So checking the size of intmax_t and uintmax_t is not useful for detecting their support.
If you want to check if you have support for __int128 or unsigned __int128, simply try to use them.
__int128 i = 0;
unsigned __int128 u = 0;
If both uintmax_t and unsigned __int128 are too small, you can still use extended precision math, such as by using two 64-bit integers in the manner showed in Maxim Egorushkin's answer.
One portable option is to construct a counter out of multiple smaller units:
typedef struct BigCounterC {
uint64_t count_[2];
} BigCounterC;
void BigCounterC_increment(BigCounterC* counter) {
// Increment the higher units when the lower unit of unsigned type wraps around reaching 0.
for(size_t n = sizeof counter->count_ / sizeof *counter->count_; n-- && !++counter->count_[n];);
}
int main() {
BigCounterC c2 = {0}; // Zero-initialize.
BigCounterC_increment(&c2);
return 0;
}
C++ version:
#include <cstdint>
#include <type_traits>
template<class Unit, size_t N>
struct BigCounter {
static_assert(std::is_unsigned_v<Unit>); // Unsigned overflow is well defined.
Unit count_[N] = {}; // Zero-initialize.
BigCounter& operator++() noexcept {
// Increment the higher units when the lower unit of unsigned type wraps around reaching 0.
for(auto n = N; n-- && !++count_[n];);
return *this;
}
};
int main() {
BigCounter<uint64_t, 2> c;
++c;
}

Generating random 64/32/16/ and 8-bit integers in C

I'm hoping that somebody can give me an understanding of why the code works the way it does. I'm trying to wrap my head around things but am lost.
My professor has given us this code snippet which we have to use in order to generate random numbers in C. The snippet in question generates a 64-bit integer, and we have to adapt it to also generate 32-bit, 16-bit, and 8-bit integers. I'm completely lost on where to start, and I'm not necessarily asking for a solution, just on how the original snippet works, so that I can adapt it form there.
long long rand64()
{
int a, b;
long long r;
a = rand();
b = rand();
r = (long long)a;
r = (r << 31) | b;
return r;
}
Questions I have about this code are:
Why is it shifted 31 bits? I thought rand() generated a number between 0-32767 which is 16 bits, so wouldn't that be 48 bits?
Why do we say | (or) b on the second to last line?
I'm making the relatively safe assumption that, in your computer's C implementation, long long is a 64-bit data type.
The key here is that, since long long r is signed, any value with the highest bit set will be negative. Therefore, the code shifts r by 31 bits to avoid setting that bit.
The | is a logical bit operator which combines the two values by setting all of the bits in r which are set in b.
EDIT:
After reading some of the comments, I realized that my answer needs correction. rand() returns a value no more than RAND_MAX which is typically 2^31-1. Therefore, r is a 31-bit integer. If you shifted it 32 bits to the left, you'd guarantee that its 31st bit (0-up counting) would always be zero.
rand() generates a random value [0...RAND_MAX] of questionable repute - but let us set that reputation aside and assume rand() is good enough and it is a
Mersenne number (power-of-2 - 1).
Weakness to OP's code: If RAND_MAX == pow(2,31)-1, a common occurrence, then OP's rand64() only returns values [0...pow(2,62)). #Nate Eldredge
Instead, loop as many times as needed.
To find how many random bits are returned with each call, we need the log2(RAND_MAX + 1). This fortunately is easy with an awesome macro from Is there any way to compute the width of an integer type at compile-time?
#include <stdlib.h>
/* Number of bits in inttype_MAX, or in any (1<<k)-1 where 0 <= k < 2040 */
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
#define RAND_MAX_BITWIDTH (IMAX_BITS(RAND_MAX))
Example: rand_ul() returns a random value in the [0...ULONG_MAX] range, be unsigned long 32-bit, 64-bit, etc.
unsigned long rand_ul(void) {
unsigned long r = 0;
for (int i=0; i<IMAX_BITS(ULONG_MAX); i += RAND_MAX_BITWIDTH) {
r <<= RAND_MAX_BITWIDTH;
r |= rand();
}
return r;
}

Porting ASM function for finding least significant set bit into C [duplicate]

this is sort of a follow up on some previous questions on bit manipulation. I modified the code from this site to enumerate strings with K of N bits set (x is the current int64_t with K bits set, and at the end of this code it is the lexicographically next integer with K bits set):
int64_t b, t, c, m, r,z;
b = x & -x;
t = x + b;
c = x^t;
// was m = (c >> 2)/b per link
z = __builtin_ctz(x);
m = c >> 2+z;
x = t|m;
The modification using __builtin_ctz() works fine as long as the least significant one bit is in the lower DWORD of x, but if is not, it totally breaks. This can be seen with the following code:
for(int i=0; i<64; i++) printf("i=%i, ctz=%i\n", i, __builtin_ctz(1UL << i));
which prints for GCC version 4.4.7:
i=0, ctz=0
i=1, ctz=1
i=2, ctz=2
...
i=30, ctz=30
i=31, ctz=31
i=32, ctz=0
or for icc version 14.0.0 something similar (except i>32 gives random results, not zero). Using division instead of shifting by 2+z works in both cases, but it's about 5x slower on my Sandy Bridge Xeon. Are there other intrinsics I should be using for 64-bit, or will I have to do some inline assembler?
Thanks!
__builtin_ctz takes arguments of type unsigned int, which is 32-bits on most platforms.
If long is 64 bits, you can use __builtin_ctzl which takes unsigned long. Or you can use __builtin_ctzll which takes unsigned long long - In this case you should use 1ULL << i instead of 1UL << i.

where is the high part of a double number stored in memory?

Hello I have a question regarding doubles. I am on IA32 machine and want to see how double is represented in memory. Below I have a program.
int main(int argc, char *argv[])
{
double d = 0.333333333333333314829616256247390992939472198486328125; //in hex: 3FD5 5555 5555 5555
printf("%x\n", d); //prints 55555555
return 0;
}
For some reason this only prints the latter 4 bytes which is 5555555. My question is where are the high bits (3FD5 5555) stored? is it at address (&d + 4)? or (&d - 4) or somewhere else defined in memory? Since double has 8 bytes how is it stored on a 32 bit machine?
I'm not going to say the following is "correct" by any means, but it Works Here (TM) - or really on whatever compiler/machine ideone uses (for the continuation of this answer I will assume it is a modern x86 target) - and can be used for examining the individual bytes/bits of the double value.
#include <stdio.h>
int main(void) {
double d = (double)1/3;
unsigned char *x = (unsigned char *)&d;
printf("chars: %2x%2x %2x%2x %2x%2x %2x%2x\n",
x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]);
// as per Yu Hao's answer
long long dd = *(long long*)&d;
printf("lld : %8llx\n", dd);
return 0;
}
Result:
chars: 5555 5555 5555 d53f // raw view doesn't account for LE/reversal
lld : 3fd5555555555555 // this is the "correct" value
The values in the two outputs are different due to the little-endian nature (within each pair of bytes) of how the integer is encoded in memory (and that the MSB affects the magnitude the most), while the individual chars are "in sequence of memory".
With 1234.5678 as input the results are:
chars: adfa 5c6d 454a 9340
lld : 40934a456d5cfaad
And with some unscrambling, a correlation can be seen:
chars: AAaa BBbb CCcc DDdd
lld : ddDDccCCbbBBaaAA
In most machines today, double has 8 bytes, try using long long(at least 64 bits) like this:
printf("%llx\n", *(long long*)(&d));
A portable method to see the hexadecimal nature of a double. "%a" prints double in hexadecimal significand and decimal exponent notation.
printf("%a\n", d);
A not completely, but reasonable portable method.
This works even if long long is more than 8 bytes.
(A long long that is not the same size as double is uncommon these days.)
#include <inttypes.h>
...
printf("%016" PRIX64 "\n", *(uint64_t *) &d);`

Overflow Error, RMS value shown wrong

I am measuring AC Voltage and I am calculating rms value for ADC.
I have an array which is having 128 samples of my signal.
while squaring number I get an error.
unsigned long int calval=0;
unsigned int loop;
float adcbufval;
for(loop=0;loop<128;loop++)
{
printf("adcval %d = %d\t ", loop, adc_temp[loop]);
calval = (adc_temp[loop])*(adc_temp[loop]);
printf("\t %ld \n", calval);
}
output:
adcval 1 = 168 28224
adcval 2 = 32 1024
adcval 3 = -88 7744
adcval 4 = -211 44521 // sqr(211) 44521 , it fine here
adcval 5 = -314 33060 // sqr(314) 98596-65536 = 33060 instead of 98596.
adcval 6 = -416 41984
adcval 7 = -522 10340
adcval 8 = -655 35809
adcval 9 = -773 7705
adcval 10 = -889 3889
Though I defined 'calval' as unsigned long int (range 0-4,294,967,295), it get over flowed at 65536 value.
In normal C compiler its working fine.
Any suggestions?
Hardware is dsPIC30f5011 / MPLAB 8.8x
You haven't shown it (or I've overlooked it), but if adc_temp[] is an array of int, then to safely square the values you must cast at least one side of the multiplication to long before doing so. Otherwise the result of the multiplication will still be int, and it will only be converted to unsigned long for the assignment, after overflow has already occurred.
Like so:
calval = (long)(adc_temp[loop])*(adc_temp[loop]);
That cast may be unsigned long if adc_temp[] is also unsigned.
According to the datasheet the dsPIC30f5011 is a 16bit microcontroller, according to C99 you are correct unsigned long should be 2^32. However it appears that the compiler you are using treats long as an alias for int which is still compliant with C90 which simply required sizeof(short) <= sizeof(int) <= sizeof(long). You might have better luck if you really need 32bit math using unsigned long long.

Resources