why am I getting a negative value in taking a timestamp? - c

Uint64_t a;
Uint32 b;
a= clock_cycles();
b= uint32((a*1000000)/(SYSPAGE_ENTRY(qtime)->cycles_per_sec));
printf("RECEIVE from Time in microseconds: %ld\n", b);
I created the variable and taking the timestamp and converting that into uint32 as shown in the above code.
If I print the b value then I am getting negative value!!
What's wrong in doing like above ??

Your b is larger than 2^31. Printf format "%ld" indicates you are going to print a signed integer and printf interprets numbers with highest bit as negative integers. Use "%lu" instead of "%ld".
Also when looking at your code, the numeric value of a*1000000 is very probable to overflow over maximal possible value. In your case, I'd suggest to use another function to get microsecond time, for example gettimeofday and to store the result in a 64-bit integer.

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)

Size of a float variable and compilation

I'm struggling to understand the behavior of gcc in this. The size of a float is of 4 bytes for my architecture. But I can still store a 8 bytes real value in a float, and my compiler says nothing about it.
For example I have :
#include <stdio.h>
int main(int argc, char** argv){
float someFloatNumb = 0xFFFFFFFFFFFF;
printf("%i\n", sizeof(someFloatNumb));
printf("%f\n", someFloatNumb);
printf("%i\n", sizeof(281474976710656));
return 0;
}
I expected the compiler to insult me, or displaying a disclaimer of some sort, because I shouldn't be able to something like that, at least I think it's kind of twisted wizardry.
The program simply run :
4
281474976710656.000000
8
So, if I print the size of someFloatNumb, I get 4 bytes, which is expected. But the affected value isn't, as seen just below.
So I have a few questions:
Does sizeof(variable) simply get the variable type and return sizeof(type), which in this case would explain the result?
Does/Can gcc grow the capacity of a type? (managing multiple variables behind the curtains to allow us that sort of things)
1)
Does sizeof(variable) simply get the variable type and return sizeof(type), which in this case would explain the result ?
Except for variable-length arrays, sizeof doesn't evaluate its operand. So yes, all it cares is the type. So sizeof(someFloatNumb) is 4 which is equivalent to sizeof(float). This explains printf("%i\n", sizeof(someFloatNumb));.
2)
[..] But I can still store a 8 bytes real value in a float, and my compiler says nothing about it.
Does/Can gcc grow the capacity of a type ? (managing multiple variables behind the curtains to allow us that sort of things)
No. Capacity doesn't grow. You simply misunderstood how floats are represented/stored. sizeof(float) being 4 doesn't mean
it can't store more than 2^32 (assuming 1 byte == 8 bits). See Floating point representation.
What the maximum value of a float can represent is defined by the constant FLT_MAX (see <float.h>). sizeof(someFloatNumb) simply yields how many bytes the object (someFloatNumb) takes up in memory which isn't necessarily equal to the range of values it can represent.
This explains why printf("%f\n", someFloatNumb); prints the value as expected (and there's no automatic "capacity growth").
3)
printf("%i\n", sizeof(281474976710656));
This is slightly more involved. As said before in (1), sizeof only cares about the type here. But the type of 281474976710656 is not necessarily int.
The C standard defines the type of integer constants according to the smallest type that can represent the value. See https://stackoverflow.com/a/42115024/1275169 for an explanation.
On my system 281474976710656 can't be represented in an int and it's stored in a long int which is likely to be case on your system as well. So what you see is essentially equivalent to sizeof(long).
There's no portable way to determine the type of integer constants. But since you are using gcc, you could use a little trick with typeof:
typeof(281474976710656) x;
printf("%s", x); /* deliberately using '%s' to generate warning from gcc. */
generates:
warning: format ‘%s’ expects argument of type ‘char *’, but argument 2
has type ‘long int’ [-Wformat=]
printf("%s", x);
P.S: sizeof results a size_t for which the correct format specifier is %zu. So that's what you should be using in your 1st and 3rd printf statements.
This doesn't store "8 bytes" of data, that value gets converted to an integer by the compiler, then converted to a float for assignment:
float someFloatNumb = 0xFFFFFFFFFFFF; // 6 bytes of data
Since float can represent large values, this isn't a big deal, but you will lose a lot of precision if you're only using 32-bit floats. Notice there's a slight but important difference here:
float value = 281474976710656.000000;
int value = 281474976710655;
This is because float becomes an approximation when it runs out of precision.
Capacities don't "grow" for standard C types. You'll have to use a "bignum" library for that.
But I can still store a 8 bytes real value in a float, and my compiler
says nothing about it.
That's not what's happening.
float someFloatNumb = 0xFFFFFFFFFFFF;
0xFFFFFFFFFFFF is an integer constant. Its value, expressed in decimal, is 281474976710655, and its type is probably either long or long long. (Incidentally, that value can be stored in 48 bits, but most systems don't have a 48-bit integer type, so it will probably be stored in 64 bits, of which the high-order 16 bits will be zero.)
When you use an expression of one numeric type to initialize an object of a different numeric type, the value is converted. This conversion doesn't depend on the size of the source expression, only on its numeric value. For an integer-to-float conversion, the result is the closest representation to the integer value. There may be some loss of precision (and in this case, there is). Some compilers may have options to warn about loss of precision, but the conversion is perfectly valid so you probably won't get a warning by default.
Here's a small program to illustrate what's going on:
#include <stdio.h>
int main(void) {
long long ll = 0xFFFFFFFFFFFF;
float f = 0xFFFFFFFFFFFF;
printf("ll = %lld\n", ll);
printf("f = %f\n", f);
}
The output on my system is:
ll = 281474976710655
f = 281474976710656.000000
As you can see, the conversion has lost some precision. 281474976710656 is an exact power of two, and floating-point types generally can represent those exactly. There's a very small difference between the two values because you chose an integer value that's very close to one that can be represented exactly. If I change the value:
#include <stdio.h>
int main(void) {
long long ll = 0xEEEEEEEEEEEE;
float f = 0xEEEEEEEEEEEE;
printf("ll = %lld\n", ll);
printf("f = %f\n", f);
}
the apparent loss of precision is much larger:
ll = 262709978263278
f = 262709979381760.000000
0xFFFFFFFFFFFF == 281474976710655
If you init a float with that value, it will end up being
0xFFFFFFFFFFFF +1 == 0x1000000000000 == 281474976710656 == 1<<48
That fits easily in a 4byte float, simple mantisse, small exponent.
It does however NOT store the correct value (one lower) because that IS hard to store in a float.
Note that the " +1" does not imply incrementation. It ends up one higher because the representation can only get as close as off-by-one to the attempted value. You may consider that "rounding up to the next power of 2 mutliplied by whatever the mantisse can store". Mantisse, by the way, usually is interpreted as a fraction between 0 and 1.
Getting closer would indeed require the 48 bits of your initialisation in the mantisse; plus whatever number of bits would be used to store the exponent; and maybe a few more for other details.
Look at the value printed... 0xFFFF...FFFF is an odd value, but the value printed in your example is even. You are feeding the float variable with an int value that is converted to float. The conversion is loosing precision, as expected by the value used, which doesn't fit in the 23 bits reserved to the target variable mantissa. And finally you get an approximation with is the value 0x1000000....0000 (the next value, which is the closest value to the one you used, as posted #Yunnosch in his answer)

C printf integer type U32

I have the hex value 0x5a800000000b and I'm trying to get a printf statement in C to print it to the console.
So far (because I'm useless in C) I'm able to get the 'b' to print, using the syntax:
printf("Hex value%x\n", value);
The value is stored in an integer type U32, but after trying all different combinations of %llx, %lx, I just keep getting compiler warnings.
I'm guessing that I'm getting the printf syntax wrong, but I can't seem to find the right % option, can someone help me out?
Thanks
It's not a problem with the printf.
The problem is that a 32 bits variable cannot hold the value 0x5a800000000b. 32 bits can hold only 8 hex digits: 0x0000000b. Hence the b on output.
To store such a large value, you should use a 64 bits variable.
long long value = 0x5a800000000bLL
Note also the double L at the end. It tells the compiler that the constant is also a long long.
Then you can use %llx in the printf format string.
There are some pre-defined macro for these types:
#include <inttypes.h>
int64_t PRId64. PRIi64
int32_t PRId32, PRIi32
int16_t PRId16, PRIi16
int8_t PRId8, PRIi8
For example:
printf("%"PRId32"\n", my32Int);
The value 0x5a800000000b is more that 32 bits, so you have to use a long.
long value = 0x5a800000000bl;
printf("Hex value%lx\n", value);
Note that hex constant should end in l,.

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

greater integer width

i m trying to enter a five digit number greater than 32767 and i used "unsigned" while declaring int number, and when i m trying to print the same number it prints some arbitary negative number,
results get overflowed......
pls help me out
Without seeing your code, I am guessing you are using %d or %i in the printf statement. Use %u instead.
Print unsigned values using "%u" instead of "%d".
Until you show some of the code, I can't be sure of anything.
But AFAIK you shouldn't be able to print out a negative number if you're printing out an uint – even if it overflows, the integer will always hold a positive number, as far as C is concerned.
So there's something else wrong.
Use correct format specifier.
%d for int
%u for unsigned int.
Using incorrect format specifier in printf() may cause Undefined Behavior.
For example, the following code invokes Undefined Behavior(UB).
#include<stdio.h>
int main(void)
{
unsigned int z=Some_value; /*Some_value is an unsigned int */
printf("%d",z);
/*UB as format specifier for unsigned int is incorrect,it should be %u not %d*/
}
I guess int is 16bit on your machine/compiler.
Though I don't know what your platform is, I guess that long would solve your problem (it is 32bit or more on all platforms I know). Print it with %ld instead of %d.
Don't get tempted to use unsigned and %u, because they will just give you numbers up to 65536, and I guess that you want more.

Resources