C++ double wierd behaviour during incrementing in for loop - c++

I was making a progress bar when I noticed this, Something wierd is happening when incrementing doubles in for loop.
EDIT : I am not asking why floating points are broken !! My issue is that the for loop is iterating one extra time in case 1 and one less time in case 4 !
I have created 4 test cases. Please See the code below :-
#include <iostream>
using namespace std;
int main()
{
cout << endl << "Should End on 0.9 :-" << endl; // Abnormal
for (double i = 0 ; i < 1 ; i += 0.1) cout << i << endl;
cout << endl << "Should End on 1 :-" << endl;
for (double i = 0 ; i <= 1 ; i += 0.1) cout << i << endl;
cout << endl << "Should End on 0.99 :-" << endl;
for (double i = 0 ; i < 1 ; i += 0.01) cout << i << endl;
cout << endl << "Should End on 1 :-" << endl; // Abnormal
for (double i = 0 ; i <= 1 ; i += 0.01) cout << i << endl;
}
Output :-
Should End on 0.9 :-
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1
Should End on 1 :-
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1
Should End on 0.99 :-
0
0.01
0.02
0.03
0.04
0.05
0.06
0.07
0.08
0.09
0.1
0.11
0.12
0.13
0.14
0.15
0.16
0.17
0.18
0.19
0.2
0.21
0.22
0.23
0.24
0.25
0.26
0.27
0.28
0.29
0.3
0.31
0.32
0.33
0.34
0.35
0.36
0.37
0.38
0.39
0.4
0.41
0.42
0.43
0.44
0.45
0.46
0.47
0.48
0.49
0.5
0.51
0.52
0.53
0.54
0.55
0.56
0.57
0.58
0.59
0.6
0.61
0.62
0.63
0.64
0.65
0.66
0.67
0.68
0.69
0.7
0.71
0.72
0.73
0.74
0.75
0.76
0.77
0.78
0.79
0.8
0.81
0.82
0.83
0.84
0.85
0.86
0.87
0.88
0.89
0.9
0.91
0.92
0.93
0.94
0.95
0.96
0.97
0.98
0.99
Should End on 1 :-
0
0.01
0.02
0.03
0.04
0.05
0.06
0.07
0.08
0.09
0.1
0.11
0.12
0.13
0.14
0.15
0.16
0.17
0.18
0.19
0.2
0.21
0.22
0.23
0.24
0.25
0.26
0.27
0.28
0.29
0.3
0.31
0.32
0.33
0.34
0.35
0.36
0.37
0.38
0.39
0.4
0.41
0.42
0.43
0.44
0.45
0.46
0.47
0.48
0.49
0.5
0.51
0.52
0.53
0.54
0.55
0.56
0.57
0.58
0.59
0.6
0.61
0.62
0.63
0.64
0.65
0.66
0.67
0.68
0.69
0.7
0.71
0.72
0.73
0.74
0.75
0.76
0.77
0.78
0.79
0.8
0.81
0.82
0.83
0.84
0.85
0.86
0.87
0.88
0.89
0.9
0.91
0.92
0.93
0.94
0.95
0.96
0.97
0.98
0.99
[Program finished]
First case should end on 0.9 but it's ending on 1
And 4th case should end on 1 but it's ending on 0.99
2nd and 3rd case are working normally.
Any ideas what's going on here ?
What am I doing wrong ?
I am using Clang compiler on aarch64 cpu.

The answer is that floating points are "broken" - or at least not trusted for exact values.
In loop 1, when it unexpectedly prints 1.0, the actual value is slightly less (0.999...), so the check that it is less than 1 is still true.
In loop 4, when you expect it to print 1.0, the actual value is slightly higher (1.0001 or something), so the check that it is <= 1 fails.

Related

How do I plot data in a text file depending on the the value present in one of the columns

I have a text file with with a header and a few columns, which represents results of experiments where some parameters were fixed to obtain some metrics. the file is he following format :
A B C D E
0 0.5 0.2 0.25 0.75 1.25
1 0.5 0.3 0.12 0.41 1.40
2 0.5 0.4 0.85 0.15 1.55
3 1.0 0.2 0.11 0.15 1.25
4 1.0 0.3 0.10 0.11 1.40
5 1.0 0.4 0.87 0.14 1.25
6 2.0 0.2 0.23 0.45 1.55
7 2.0 0.3 0.74 0.85 1.25
8 2.0 0.4 0.55 0.55 1.40
So I want to plot x = B, y = C for each fixed value of And E so basically for an E=1.25 I want a series of line plots of x = B, y = C at each value of A then a plot for each unique value of E.
Anyone could help with this?
You could do a combination of groupby() and seaborn.lineplot():
for e,d in df.groupby('E'):
fig, ax = plt.subplots()
sns.lineplot(data=d, x='B', y='C', hue='A', ax=ax)
ax.set_title(e)

How did they convert IR-Lock pixels to a position on a normal plane 1m in front of the lens

I am working on tracking a moving target using Quadcopter. In my project, I am using an IR-Camera which is a modified version of the Pixy camera, but for detecting IR targets. While I was studying their code I found a part where I couldn't understand it. I tried googling it but didn't find anything or any formula related to it. So I wonder if someone can give me some tips on what equations or formula they used.
Here is the part I didn't understand.
/*
converts IRLOCK pixels to a position on a normal plane 1m in front of the lens based
on a characterization of IR-LOCK with the standard lens, focused such that 2.38mm
of threads are exposed
*/
void AP_IRLock_I2C::pixel_to_1M_plane(float pix_x, float pix_y, float &ret_x, float &ret_y)
{
ret_x = (-0.00293875727162397f*pix_x + 0.470201163459835f)/
(4.43013552642296e-6f*((pix_x - 160.0f)*(pix_x - 160.0f))
+ 4.79331390531725e-6f*((pix_y - 100.0f)*(pix_y - 100.0f)) - 1.0f);
ret_y = (-0.003056843086277f*pix_y + 0.3056843086277f)/
(4.43013552642296e-6f*((pix_x - 160.0f)*(pix_x - 160.0f))
+ 4.79331390531725e-6f*((pix_y - 100.0f)*(pix_y - 100.0f)) - 1.0f);
You can find the rest of the code here.
IRlock Ardupilot
Let's focus on the equation for ret_x, which simplified is like this:
ret_x = (-0.0029 * pix_x + 0.47) /
(4.4e-6 * (pix_x - 160.0)^2 + 4.8e-6 * (pix_y - 100.0)^2 - 1.0);
First, notice the 160 and 100 magic numbers. The Pixy capture resolution is 320x200, so these are there to translate pixel coordinates from a space where (0,0) is in the corner to where it is in the center. So if pix_x is 160 and pix_y is 100, that is the center of the frame, and the denominator will be -1.
The rest of it appears to be a lens correction. Here are the values of ret_x that you get across the range of valid pix_x and pix_y inputs:
0 40 80 120 160 200 240 280 320
0 -0.56 -0.40 -0.25 -0.12 0.00 0.12 0.25 0.40 0.56
20 -0.55 -0.39 -0.25 -0.12 0.00 0.12 0.25 0.39 0.55
40 -0.54 -0.38 -0.25 -0.12 0.00 0.12 0.25 0.38 0.54
60 -0.53 -0.38 -0.24 -0.12 0.00 0.12 0.24 0.38 0.53
80 -0.53 -0.38 -0.24 -0.12 0.00 0.12 0.24 0.38 0.53
100 -0.53 -0.38 -0.24 -0.12 0.00 0.12 0.24 0.38 0.53
120 -0.53 -0.38 -0.24 -0.12 0.00 0.12 0.24 0.38 0.53
140 -0.53 -0.38 -0.24 -0.12 0.00 0.12 0.24 0.38 0.53
160 -0.54 -0.38 -0.25 -0.12 0.00 0.12 0.25 0.38 0.54
180 -0.55 -0.39 -0.25 -0.12 0.00 0.12 0.25 0.39 0.55
200 -0.56 -0.40 -0.25 -0.12 0.00 0.12 0.25 0.40 0.56
So as expected, ret_x is near 0 for pixels near the center (pix_x == 160). And it reaches +/- 0.56 at the extremes, which suggests a horizontal field of view of approximately 120 degrees (from trigonometry, 2*0.56 meter width at 1 meter distance).
The horizontal correction is slightly influenced by the vertical coordinate, notably near the corners. This is presumably to correct for spherical distortion in the lens (which is common).
The astute will recognize that the equation is slightly defective: given pixel coordinates in [0,319] and [0,199], the center values should be 159.5 and 99.5, not 160 and 100.

How to plot a multiindex dataframe having suplots for the first level index?

I have a pandas multiindex dataframe with quarters 1-4 and hours 0-23 as the index.
The data Looks like this
quarter hour value1 value2 value3
1 0 0.06 0.47 0.50
1 1 0.65 0.04 0.65
1 2 0.58 0.10 0.60
1 3 0.51 0.07 0.17
...
4 20 0.82 0.17 0.96
4 21 0.08 0.98 0.09
4 22 0.73 0.43 0.73
4 23 0.99 0.85 0.42
How can I plot 4 linegraphs as subplots in a 2x2 arrangement having Q1 and Q4 on the top and Q2 and Q3 on the bottom?
I have been trying with
f, ((ax1, ax4), (ax2, ax3)) = plt.subplots(2, 2, sharex='col', sharey='row')
ax1.plot(df.loc[1])
But it doesnt seem to work.

How do I refer to the current line/observation number in a loop in the data step?

For example, I have data on various latencies that I iterate through and apply a linear function to, as shown: (the function is just an example here)
data latency;
input lat1 - lat20;
array cost[20];
array lat[20];
do x = 1 to 20;
cost[x] = lat[x] * 1.875;
end;
drop x;
datalines;
0.42 0.85 0.59 0.06 0.21 0.35 0.1 0.08 0.85 0.53 0.81 0.44 0.47 0.2 0.99 0.32 0.18 0.87 0.33 0.84
0.11 0.83 0.02 0.59 0.74 0.65 0.76 0.45 0.57 0.22 0.2 0.13 0.42 0.15 0.05 0.51 0.48 0.95 0.39 0.92
0.8 0.9 0.65 0.29 0.77 0.0 0.24 0.05 0.16 0.72 0.58 0.9 0.35 0.63 0.79 0.41 0.73 0.36 0.82 0.16
0.74 0.21 0.57 0.73 0.83 0.78 0.77 0.92 0.13 0.39 0.52 0.14 0.1 0.77 0.68 0.99 0.26 0.37 0.97 0.83
;
run;
How can I save a variable with the current observation number in each iteration of the loop, so that I can use it in calculations later?
I know that proc print will automatically print the observation number, but how do I access this and store it to a variable in the data step? Is there a way to do this as sas reads the datalines line by line?
I tried this, but then the obs variable is 2 for every observation.
data latency;
input lat1 - lat20;
obs = 1; * ADDED LINE;
array cost[20];
array lat[20];
do x = 1 to 20;
cost[x] = lat[x] * 1.875;
end;
obs = obs + 1; * ADDED LINE;
drop x;
datalines;
0.42 0.85 0.59 0.06 0.21 0.35 0.1 0.08 0.85 0.53 0.81 0.44 0.47 0.2 0.99 0.32 0.18 0.87 0.33 0.84
0.11 0.83 0.02 0.59 0.74 0.65 0.76 0.45 0.57 0.22 0.2 0.13 0.42 0.15 0.05 0.51 0.48 0.95 0.39 0.92
0.8 0.9 0.65 0.29 0.77 0.0 0.24 0.05 0.16 0.72 0.58 0.9 0.35 0.63 0.79 0.41 0.73 0.36 0.82 0.16
0.74 0.21 0.57 0.73 0.83 0.78 0.77 0.92 0.13 0.39 0.52 0.14 0.1 0.77 0.68 0.99 0.26 0.37 0.97 0.83
;
run;
proc print data=latency;
run;
This is a small example, but in reality I can't simply add a new variable that stores the line number to the start of each data line and read it in. That isn't practical for the actual data set.
You just need to add a retain statement so SAS doesn't reset obs to 0 at every new observation.
data latency;
retain obs 0;
obs = obs + 1;
...
run;
Your first attempt was very close. Try again, but this time replace this line:
obs = 1; * ADDED LINE;
With this:
retain obs 0; * ADDED LINE;
That way, your obs variable will be retained across your entire dataset instead of being reset to 1 each time.

Strange profiler behavior: same functions, different performances

I was learning to use gprof and then i got weird results for this code:
int one(int a, int b)
{
int i, r = 0;
for (i = 0; i < 1000; i++)
{
r += b / (a + 1);
}
return r;
}
int two(int a, int b)
{
int i, r = 0;
for (i = 0; i < 1000; i++)
{
r += b / (a + 1);
}
return r;
}
int main()
{
for (int i = 1; i < 50000; i++)
{
one(i, i * 2);
two(i, i * 2);
}
return 0;
}
and this is the profiler output
% cumulative self self total
time seconds seconds calls us/call us/call name
50.67 1.14 1.14 49999 22.80 22.80 two(int, int)
49.33 2.25 1.11 49999 22.20 22.20 one(int, int)
If i call one then two the result is the inverse, two takes more time than one
both are the same functions, but the first calls always take less time then the second
Why is that?
Note: The assembly code is exactly the same and code is being compiled with no optimizations
I'd guess it is some fluke in run-time optimisation - one uses a register and the other doesn't or something minor like that.
The system clock probably runs to a precision of 100nsec. The average call time 30nsec or 25nsec is less than one clock tick. A rounding error of 5% of a clock tick is pretty small. Both times are near enough zero.
My guess: it is an artifact of the way mcount data gets interpreted. The granularity for mcount (monitor.h) is on the order of a 32 bit longword - 4 bytes on my system. So you would not expect this: I get different reports from prof vs gprof on the EXACT same mon.out file.
solaris 9 -
prof
%Time Seconds Cumsecs #Calls msec/call Name
46.4 2.35 2.3559999998 0.0000 .div
34.8 1.76 4.11120000025 0.0000 _mcount
10.1 0.51 4.62 1 510. main
5.3 0.27 4.8929999999 0.0000 one
3.4 0.17 5.0629999999 0.0000 two
0.0 0.00 5.06 1 0. _fpsetsticky
0.0 0.00 5.06 1 0. _exithandle
0.0 0.00 5.06 1 0. _profil
0.0 0.00 5.06 20 0.0 _private_exit, _exit
0.0 0.00 5.06 1 0. exit
0.0 0.00 5.06 4 0. atexit
gprof
% cumulative self self total
time seconds seconds calls ms/call ms/call name
71.4 0.90 0.90 1 900.00 900.00 key_2_text <cycle 3> [2]
5.6 0.97 0.07 106889 0.00 0.00 _findbuf [9]
4.8 1.03 0.06 209587 0.00 0.00 _findiop [11]
4.0 1.08 0.05 __do_global_dtors_aux [12]
2.4 1.11 0.03 mem_init [13]
1.6 1.13 0.02 102678 0.00 0.00 _doprnt [3]
1.6 1.15 0.02 one [14]
1.6 1.17 0.02 two [15]
0.8 1.18 0.01 414943 0.00 0.00 realloc <cycle 3> [16]
0.8 1.19 0.01 102680 0.00 0.00 _textdomain_u <cycle 3> [21]
0.8 1.20 0.01 102677 0.00 0.00 get_mem [17]
0.8 1.21 0.01 $1 [18]
0.8 1.22 0.01 $2 [19]
0.8 1.23 0.01 _alloc_profil_buf [22]
0.8 1.24 0.01 _mcount (675)
Is it always the first one called that is slightly slower? If that's the case, I would guess it is a CPU cache doing it's thing. or it could be lazy paging by the operating system.
BTW: what optimization flags are compiling with?