Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I was writing a small Least common multiple algorithm and encountered something I don't understand. This is the first and last part of the code:
long a = 14159572;
long b = 63967072;
int rest = 4;
long long ans;
.
. // Some other code here that is not very interesting.
.
else
{
//This appears correct, prints out correct answer.
ans = b/rest;
std::cout << a*ans;
}
But if I change the last "else" to this it gives an answer that is much smaller and incorrect:
else
{
std::cout << a*(b/rest);
}
Anyone know why this is? I don't think it's an overflow since it was no negative number that came out wrong, but rather just a much smaller integer (around 6*10^8) than the actual answer (around 2.2*10^14). As far as I understand it should calculate "b/rest" first in both cases, so the answers shouldn't differ?
Difference is not order of operations but data types:
ans = b/rest; // b/rest is long which upscaled to long long
std::cout << a*ans; // a converted to long long and result is long long
vs:
std::cout << a*(b/rest); // a*(b/rest) all calculations in long
so if you change your second variant to:
std::cout << a*static_cast<long long>(b/rest);
you should see the same result.
Update to why your cast did not work, note the difference:
long a,b;
// divide `long` by `long` and upscale result to `long long`
std::cout << static_cast<long long>( a / b );
// upscale both arguments to `long long` and divide `long long` by `long long`
std::cout << a / static_cast<long long>( b );
You're still encountering overflow. Just because you're not observing a negative number doesn't mean there's no overflow.
In your case specifically, long is almost certainly a 32-bit integer, as opposed to long long which is probably a 64-bit integer.
Since the maximum value of a 32-bit signed integer is roughly 2 billion, 14159572 * (63967072 / 4) is most definitely overflowing the range.
Make sure you perform your calculations using long long numbers, or else reconsider your code to avoid overflow in the first place.
The compiler assumes data types for each operand of your math equation and does the multiplication and division according to those assumed data types (refer to "integer division"). This also applies to intermediates of the computation. This also applies to the result passed to the stream since you don't pass a variable of an explicitly defined type.
Related
I've seen a couple old posts that had a similar context but the answers were code snippets, not explanatory. And I can't even get the code offered in those answers to compile.
I apologize in advance if this is poorly formatted or explained, I am new to C++ and I avoid asking questions on forums at all costs but this has become a real thorn in my side.
I am using C++ to access the memory register of an accelerometer.
This register contains 8 bits of data in the form of twos complement.
The accelerometer is set to have a range of +/- 2 g's, meaning (see section 1.5 of reference manual on page 10)
My goal is to take this twos complement data and save it to a text file as signed base-10 data.
Relevant code below:
while(1)
{
int d = 0;
d= wiringPiI2CReadReg8(fd, DATA_X_H);
d = (int8_t)d;
d = d * EIGHTBITCONV;
std::cout << d << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
I've tested the program by hard coding "d" as 01111111 (127) and the program returns "73". But hard coding "d" as 10000001 (-127) and the program returns the correct "-127".
So the program only functions properly when dealing with negative numbers.
Is this happening because when casting the float "d" to an 8bit integer it truncates the leading zero for positive numbers? How would I fix this?
Link to datasheet: https://www.mouser.com/datasheet/2/348/KX132-1211-Technical-Reference-Manual-Rev-1.0-1652679.pdf
You do not need to convert from 2's complement to "signed integer", because 2's complement is signed integer.
You are only reading 8 bits, but int (the return type of wiringPiI2CReadReg8) has more. So you need a sign-extend conversion. Something like:
int result = (int)(signed char)wiringPiI2CReadReg8(fd, DATA_X_H);
The (int) conversion is implicit and can be omitted. And in your case you are converting to a float (The conversion is again implicit). So:
d = (signed char)wiringPiI2CReadReg8(fd, DATA_X_H);
Actually your solution (negating twice) would work as well. More explicitly it could be written like this (since 1 is int):
d = -((int)(~(int8_t)d) + 1);
But this is just unnecessary work. It could be simplified to be:
d = -(-(int8_t)d);
and now it is obviously simplifies into:
d = (int8_t)d;
same as what I wrote before.
Ok so I think a lot of my confusion came from the fact that I was trying hard code values into my program without proper knowledge of how to do so.
If I were to do hard coding as a method to test the logic, I should have specified that the values of "d" were binary.
So it looks like my original code, while extremely sloppy, was functioning properly.
How does std::cout work?
The following code doesn't pass certain test cases for a question on HackerEarth.com:
double n,a,b;
while(t--){
cin>>n>>a>>b;
long long x = round(b*n*1.0/(a+b));
cout<<((a*x*x) + b*(n-x)*(n-x))<<endl;
}
while, the following one passes all of them:
double n,a,b;
while(t--){
cin>>n>>a>>b;
long long x = round(b*n*1.0/(a+b));
long long ans = (a*x*x) + b*(n-x)*(n-x);
cout<<ans<<endl;
}
Why does it happen that when I store the calculated value in a variable, then only the test cases are passed?
Does the value change if directly printed to console?
I am a newbie to C++.
The output format "chosen" by cout (or any std::ostream) depends on the type which is being outputted (specifically, it depends on the implementation of operator<< for that type).
Let's look at what types are at play in both cases.
In your first example, you are outputting a double, since a, b, and n are doubles. Even though x is a long long, the expression is a double due implicit conversions.
In the second example, you are outputting a long long, since that is the type of ans. Note that your calculation of ans may be truncated, since it is being computed as a double (for the reasons explained above) but stored in a long long.
Without knowing the details of the test cases you are talking about, one difference in the output is that doubles will likely be output in decimal notation (e.g. 1.23 or 1.0) whereas a long long (or any integral type) will be output as a whole number (note: there are ways to change this behavior, which I'm omitting here for simplicity).
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have tried to access values stored in a vector in reverse order. The following code shows no error:
for (long long int i = 0; i < end.size(); i++)
cout << end[end.size() - 1 - i] << "\n";
But the following code shows runtime error:
for(long long int i = end.size()-1;i>=0;i--) cout<<end[i]<<"\n";
Is there any difference between the two methods?
Is there any difference between the two methods?
end.size() returns std::size_t which is an unsigned type. Given an empty vector, you subtract 1 from unsigned zero. The result is a very large unsigned number due to modular arithmetic that unsigned numbers use.
Here, the behaviour depends on the version of the language, as well as the implementation. If long long can represent the large unsigned value, then you overflow the array with this large index (any index being outside the bounds of an empty vector) and behaviour will be undefined. This would happen on 32 bit systems where std::size_t is presumably 32 bits and long long 64 bits.
If the value is unrepresentable by long long, then prior to C++20, the resulting value will be implementation defined. If that value is negative, then you have desired behaviour, other wise undefined behaviour. After C++20, the result would be congruent with a representable value modulo the number of representable values. If bit width of long long matches with std::size_t, then the result would be -1 and behaviour would be as desired.
In conclusion: Latter approach is broken on some implementations. The first one doesn't have this problem.
The proper way to do it is:
for(auto i=end.size(); i-- ;) cout << end[i] << "\n" ;
This question already has answers here:
Implicit type promotion rules
(4 answers)
Closed 3 years ago.
Have the following code:
short a = 5;
short b = 15;
short c = 25;
short d = std::min(a, b);
short e = std::min(a, b-c); // Error
The last line cannot be compiled, claiming that there's no overload of min() that matches the arguments "short, int".
What is the reason for this being the case?
I understand that the result of b-c could potentially not fit in a short anymore. However that would be the same if I were using INTs and there it doesn't automatically form a LONG or anything to enforce that it fits.
As long as I am sure that the resulting number will never exceed the range of SHORT, it is safe if I use static_cast<short>(b-c), right?
Huge thanks!
Reason: integer promotion. If a type is narrower than int, it is promoted to int automatically. This makes little difference for signed numbers because overflow is undefined, but for unsigned numbers for which overflow wraps, this allows the compiler to emit a lot less code for most processors.
Most of the time, this automatically casts back because assigning to a narrower variable is not an error. You happened to find a case where this really does cause an issue though.
If you're sure it fits, just cast it back.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
What is the faster between the two following code? why?
In which case one can be preferred to the other?
double x = (a + b) >> 1
double x = (a + b) / 2.0
These do different things so pick the one with the functionality you like: Truncating the result down or returning the 0.5 fraction.
"Premature optimization is root of all evil". Use what is more readable, when you have perfomance issue first look for algorithms and data structures, where you can get most perfomance gain, then run profiler and optimize where is necessary.
As others have said, the two statements produce different results, especially if (a + b) is an odd value.
Also, according to the language, a and b must be integral values in order to satisfy the shifting operation.
If a and b differ in type between the two statements, you are comparing apples to elephants.
Given this demo program:
#include <iostream>
#include <cstdlib>
#include <cmath>
using std::cout;
using std::endl;
int main(void)
{
const unsigned int a = 5;
const unsigned int b = 8;
double x = (a + b) >> 1;
cout << x << endl;
double y = (a + b) / 2.0;
cout << y << endl;
return EXIT_SUCCESS;
}
The output:
6
6.5
Based on this experiment, the comparison is apples to oranges. The statement involving shifting is a different operation that dividing by a floating point number.
As far as speed goes, the second statement is slower because the expression (a + b) must be converted to double before applying the division. The division is floating point, which may be slow on platforms without hardware floating point support.
You should not concern yourself on the execution speed of either statement. Of more importance is the correctness and robustness of the program. For example, the two statements above provide different results, which is a very important concern for correctness.
Most Users would wait for a program to produce correct results than have a quick program producing incorrect results or behavior (nobody is in a hurry for a program to crash).
Management would rather you spend time completing the program than wasting time optimizing portions of the program that are executed infrequently.
If a or b is a double or float, shifting will produce incorrect results.