I have a C++ class, shapeObject, that is somewhat complicated but this question is only regarding two particular fields of the class, dX and dY.
header:
class shapeObject{
public:
shapeObject();
...
private:
float dX, dY;
...
};
cpp file:
shapeObject::shapeObject(){
...
dX = 0;
dY = 0;
...
}
These fields are only modified by one function, which adds or subtracts a small float value to dX or dY. However, the next time the value of dX or dY is read, they have reverted back to their original value of 0.0 .
Since the fields are not being modified anywhere but that one function, and that function is never setting the values to 0.0, I'm not sure why they are reverting to the original value. Any ideas of why this could be happening?
My psychic debugging skills indicate some possibilities:
You're shadowing the members when you assign them float dX = small_float_value; instead of dX = small_float_value;
You're working with different copies of shapeObject and the modified one gets thrown away by accident (or its copy constructor doesn't do the obvious thing).
The values only appear to still be zero in printing but are in fact the small float value you want.
Somehow the small float value gets truncated to zero.
When adding or subtracting a small value try using cast by float like dx=dx+(float)0.001;
Better try using double instead of float.Float has some precision problem.
Perhaps somewhere the small float value is being cast to an int before being added/subtracted so the resulting change is zero?
Need to see more code to do anything more than stab in the dark.
Related
I am trying to do some precision calculations and I am interested in learning, how C++ (in my case), performs arithmetic manipulations internaly.
Say that we have the following program (I am just gonna write the body since it is not meant for actually running it)
double x = 1./3.;
double y = 0.12345;
double z = 9.* y + x*x;
What I am thinking, is that C++, takes x and stores somewhere in memory the closest binary representation that yields the (closest to) value 1./3.. Same for y.
But what happens with z? Is it doing addition/multiplication after it has represented all numbers/variables that take place, in their corresponding closest binary representation? Or something else happens.
I welcome any reference that could shed light into my question.
Computers use something called IEEE754 standard to represent floating point values (double and floats). You can read more about that standard online. And for your question, c++ compiler does something like this- first it stores number 9.0 somewhere in memory, than it reads value of variable y, multiplies those two numbers and store them in some temporary variable (lets call it tmp0). Than, it multiplies x by x, and stores that again in the temporary variable (lets call it tmp1), and than after that, it adds tmp0 and tmp1 to the variable z, and deletes tmp0 and tmp1 from memory. And yes, if that is your answer, it does first store all those variables somewhere in memory, and only after that he can evaluate the value of z.
The program takes for parameter one double and its doing computation with long float point values. eg double myvar= n*0.000005478554 /298477.
The problem is that im not sure that the real computational value is inserted to myvar.
because whenvever i change n it produce the same thing cout<<"myvar ="<<myvar;
What is the biggest type in c++ that can be used for maximum accuracy? Does a buffer overflow caused by this code because double variable cant hold too much info ? If yes what can happen and how can i detect it for later use?
double will hold values much smaller (and bigger) than 0.000005478554 /298477. Any problem that you have is almost certainly caused by a bug in your code. Show it!
Try to reduce your problem to a few lines. This kind of problems can be reproduced with something as small as
#include <iostream>
int main() {
double myvar = 7 * 0.000005478554 /298477;
std::cout << myvar;
}
I am working on c++, I have a structure with all most 100 float variables within it, and i am going to initialize them with value 0 in no argument constructor ,so which way it is faster?
Type 1:
struct info
{
//no argument constructor
info();
float x1;
float x2;
.
.
.
float x100;
}Info;
info::info()
{
float x1 = 0;
float x2 =0;
.
.
.
.
.
float x100 = 0;
}
//creation
Info* info1 = new Info();
Type2 :
typedef struct info
{
float x1;
float x2;
.
.
.
.
float x100;
}Info;
Info* infoIns = new Info;
memset(infoIns,0,sizeof(Info));
One hundred variables called x1 .. x100 just CALLS out to be an array (or if the number varies, perhaps using a vector)
In which case std::fill(x, x+100, 0.0f) would probably beat all of the choices above.
A better solution is probably to just initialize the whole object:
Info* infoIns = new Info();
or
Info infoIns = {}; // C++11
or
Info infoIns = Info();
Whenever it's a question of performance, the ONLY answer that applies is "what you can measure". I can sit here and explain exactly why in my experience, on my machine (or my machines) method A is faster than method B or method C. But if you are using a different compiler, or have a different processor, that may not apply at all, because the compiler you use is doing something different.
Regardless of which is "faster", you should use a constructor to set the values to zero. If you want to use memset, then by all means do so, but inside the constructor. That way, you won't find some place in the code where you FORGOT to set one of your structures to zero before trying to use it. Bear in mind that setting a struct/class to zero using memset is very dangerous. If the class or struct has virtual member functions (or contain some object that does), this will most likely overwrite the VPTR, which describes the virtual functions. That is a bad thing. So if you want to use memset, use it with x1 and a size of 100 *sizeof(float) (but using an array is probably a better choice again).
In the absence of measurement, clearing will likely be faster but much much nastier, and, if the code you've written is what you actually implemented, the clearing will actually work a lot better. The 2nd way you have is not particularly good style in any case, and you should use member initialisation.
I'd be more inclined to use a std::array (C++11) or a std::vector or even a plain array in any case.
2nd version, apart from already mentioned flaws, actually doesn't guarantee that float values will be 0.0 after memset.
3.9.1 Fundamental types [basic.fundamental]
8
...
The value representation of floating-point types is implementation-defined.
...
Thus you can end up with non zero values in your floating points in case of weird float representation.
There is a piece of code confuse me, which runs in windows!
Here is the code:
#define point_float2uint(x) *((unsigned int *)&x)
float divide_1000(float y)
{
float v = y / 1000.0f;
return v;
}
float divide_1000(int y)
{
float v = float(y) / 1000.0f;
return v;
}
void float_test(void)
{
int num[5] = {67975500, 67251500, 67540620, 69435500, 70171500};
for (int i = 0; i < 5; ++i)
{
int a = num[i];
float af_f = divide_1000(float(a));
float af_i = divide_1000((a));
printf("src num:%d, af_f:%f, %x, af_i:%f, %x\n", num[i], af_f, point_float2uint(af_f), af_i, point_float2uint(af_i));
}
}
Here is the output, compiled by vs2005:
src num:67975500, af_f:67975.507813, 4784c3c1, af_i:67975.500000, 4784c3c0
src num:67251500, af_f:67251.507813, 478359c1, af_i:67251.500000, 478359c0
src num:67540620, af_f:67540.625000, 4783ea50, af_i:67540.617188, 4783ea4f
src num:69435500, af_f:69435.507813, 47879dc1, af_i:69435.500000, 47879dc0
src num:70171500, af_f:70171.507813, 47890dc1, af_i:70171.500000, 47890dc0
The question is: why I use the "divide_1000", get the different result in windows? This is not what I want!
And I find that not all the integer result in different, but some just like the code above.
Here is the the output, comipled by gcc4.4.5 in debian:
src num:67975500, af_f:67975.507812, 4784c3c1, af_i:67975.507812, 4784c3c1
src num:67251500, af_f:67251.507812, 478359c1, af_i:67251.507812, 478359c1
src num:67540620, af_f:67540.625000, 4783ea50, af_i:67540.625000, 4783ea50
src num:69435500, af_f:69435.507812, 47879dc1, af_i:69435.507812, 47879dc1
src num:70171500, af_f:70171.507812, 47890dc1, af_i:70171.507812, 47890dc1
I get the same result in useing different function "divide_1000". That's what I want.
There are quite a few code generation settings involved here that affect the outcome. The difference that you report is observable in non-optimized code under default floating point model (i.e. "precise" model) when using the "classic" FPU instructions for floating-point computations.
The compiler translates the first call literally: the original integer value is first converted to float - 4-byte floating-point value - stored in memory (as function argument). This conversion rounds the value to +6.7975504e+7, which is already not precise. Later that float value is read form memory inside the first function and used for further computations.
The second call passes an int value to the function, which is directly loaded into high-precision FPU register and used for further computations. Even though you specified an explicit conversion from int to float inside the second function, the compiler decided to ignore your request. This value is never literally converted to float, meaning that the aforementioned loss of precision never occurs.
That is what is causing the difference you observed.
If you rewrite your second function as
float divide_1000(int y)
{
float fy = y;
float v = fy / 1000.0f;
return v;
}
i.e. add an additional step that saves the float value to a named location in memory, the compiler will perform that step in non-optimized code. This will cause the results to become identical.
Again, the above applies to the code compiled without optimizations, when the compiler normally attempts to translate all statements very closely (but not always exactly). In optimized code the compiler eliminates the "unnecessary" intermediate conversions to float and all "unnecessary" intermediate memory stores in both cases, producing identical results.
You might also want to experiment with other floating-point models (i.e. "strict" and "fast") to see how it affects the results. These floating-point models exist specifically to deal with issues like the one you observed.
If you change code generation settings of the compiler and make it use SSE instructions for floating-point arithmetic, the results might also change (in my experiment the difference disappears when SSE2 instruction set is used instead of FPU instructions).
double r2 = dx * dx + dy * dy;
double r3 = r2 * sqrt(r2);
Can the second line be replaced by something faster? Something that does not involve sqrt?
How about
double r3 = pow(r2,1.5);
If sqrt is implemented as a special case of pow, that will save you a multiplication. Not much in the grand scheme of things mind!
If you are really looking for greater efficiency, consider whether you really need r^3. If, for example, you are only testing it (or something derived from it) to see whether it exceeds a certain threshold, then test r2 instead e.g.
const double r3_threshold = 9;
//don't do this
if (r3 > r3_threshold)
....
//do do this
const double r2_threshold = pow(r3_threshold,2./3.);
if (r2 > r2_threshold)
....
That way pow will be called only once, maybe even at compile time.
EDIT If you do need to recompute the threshold each time, I think the answer concerning Q_rsqrt is worth a look and probably deserves to outrank this one
Use fast inverse sqrt (take the Q_rsqrt function).
You have:
float r2;
// ... r2 gets a value
float invsqrt = Q_rsqrt(r2);
float r3 = r2*r2*invsqrt; // x*x/sqrt(x) = x*sqrt(x)
NOTE: For double types there is a constant like 0x5f3759df which can help you write a function that handles also double data types.
LATER EDIT: Seems like the method has been already discussed here.
LATER EDIT2: The constant for double was in the wikipedia link:
Lomont pointed out that the "magic number" for 64 bit IEEE754 size
type double is 0x5fe6ec85e7de30da, but in fact it is close to
0x5fe6eb50c7aa19f9.
I think another way to look at your question would be "how to calculate (or approximate) sqrt(n)". From there your question would be trivial (n * sqrt(n)). Of course, you'd have to define how much error you could live with. Wikipedia gives you many options:
http://en.wikipedia.org/wiki/Methods_of_computing_square_roots