I am trying to print out an std::array as seen below, the output is supposed to consist of only booleans, but there seem to be numbers in the output aswell (also below). I've tried printing out the elements which give numbers on their own, but then I get their actual value, which is weird.
My main function:
float f(float x, float y)
{
return x * x y * y - 1;
}
int main()
{
std::array<std::array<bool, ARRAY_SIZE_X>, ARRAY_SIZE_Y> temp = ConvertToBinaryImage(&f);
for(int i = 0; i < (int)temp.size(); i)
{
for(int j = 0; j < (int)temp[0].size(); j)
{
std::cout << temp[i][j] << " ";
}
std::cout << std::endl;
}
}
The function that sets the array:
std::array<std::array<bool, ARRAY_SIZE_X>, ARRAY_SIZE_Y> ConvertToBinaryImage(float(*func)(float, float))
{
std::array<std::array<bool, ARRAY_SIZE_X>, ARRAY_SIZE_Y> result;
for(float x = X_MIN; x <= X_MAX; x = STEP_SIZE)
{
for(float y = Y_MIN; y <= Y_MAX; y = STEP_SIZE)
{
int indx = ARRAY_SIZE_X - (x - X_MIN) * STEP_SIZE_INV;
int indy = ARRAY_SIZE_Y - (y - Y_MIN) * STEP_SIZE_INV;
result[indx][indy] = func(x, y) < 0;
}
}
return result;
}
The constants
#define X_MIN -1
#define Y_MIN -1
#define X_MAX 1
#define Y_MAX 1
#define STEP_SIZE_INV 10
#define STEP_SIZE (float)1 / STEP_SIZE_INV
#define ARRAY_SIZE_X (X_MAX - X_MIN) * STEP_SIZE_INV
#define ARRAY_SIZE_Y (Y_MAX - Y_MIN) * STEP_SIZE_INV
My output:
184 225 213 111 0 0 0 0 230 40 212 111 0 0 0 0 64 253 98 0
0 0 0 0 1 0 1 0 1 1 1 1 6 1 0 0 168 0 0 0
0 183 213 111 0 0 0 0 0 0 0 0 0 0 0 0 9 242 236 108
0 0 0 1 64 1 1 0 1 1 1 1 240 1 1 1 249 1 0 0
0 21 255 0 0 0 0 0 98 242 236 108 0 0 0 0 0 0 0 0
0 0 0 1 128 1 1 0 1 1 1 1 128 1 1 1 0 1 1 0
0 1 255 1 0 1 1 0 1 1 1 1 0 1 1 1 31 1 1 1
0 0 0 0 184 225 213 111 0 0 0 0 2 0 0 0 0 0 0 0
9 1 0 1 0 1 1 0 1 1 1 1 0 1 1 1 64 1 1 1
0 1 0 1 64 1 1 0 1 1 1 1 96 1 1 1 249 1 1 1
0 1 213 1 0 1 1 0 1 1 1 1 0 1 1 1 32 1 1 1
0 1 0 1 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1
0 21 255 0 0 0 0 0 80 59 117 0 0 0 0 0 32 112 64 0
0 1 0 1 17 1 1 16 1 1 1 1 104 1 1 1 0 1 1 1
0 0 144 1 249 1 1 0 1 1 1 1 0 1 1 1 0 1 1 0
0 0 0 1 80 1 1 0 1 1 1 1 24 1 1 1 0 1 1 0
0 0 0 0 0 0 0 0 17 0 1 16 0 0 0 0 112 7 255 0
0 0 0 1 134 1 1 30 1 1 1 1 8 1 1 1 0 1 0 0
0 0 0 0 0 1 1 0 1 1 1 1 0 1 1 1 32 0 0 0
0 0 0 0 0 0 1 0 1 1 1 1 0 1 0 0 0 0 0 0
CodePudding user response:
Floating point maths will often not produce accurate results, see Is floating point math broken?.
If we print out the values of indx
and indy
:
20, 20
20, 19
20, 18
20, 17
20, 15
20, 14
20, 13
20, 13
20, 11
20, 10
20, 9
20, 9
20, 8
20, 6
20, 5
20, 5
20, 3
20, 3
20, 1
20, 1
19, 20
19, 19
19, 18
19, 17
...
You can see that you are writing to indexes with the value 20
which is out of bounds of the array and also you aren't writing to every index leaving some of the array elements uninitialised. Though normally booleans are only true
or false
they are usually actually stored as a byte allowing storing values between 0
and 255
, printing the uninitialised values is undefined behaviour.
We can fix your code in this particular instance by calculating the indexes a little more carefully:
int indx = std::clamp(int(round(ARRAY_SIZE_X - (x - X_MIN) * STEP_SIZE_INV)), 1, ARRAY_SIZE_X)-1;
int indy = std::clamp(int(round(ARRAY_SIZE_Y - (y - Y_MIN) * STEP_SIZE_INV)), 1, ARRAY_SIZE_Y)-1;
There are two fixes here, you were generating values between 1
and 20
, the -1
reduces this to 0
to 19
. The round
solves the issue of not using all the indexes (you were simply truncating by assigning to an int
). The clamp
ensures the values are always in range (though in this case the calculations work out to be in range).
As you want to always write to every pixel a better solution would be to iterate over the values of indx
and indy
and calculate the values of x
and y
from the indices:
for (int indx = 0; indx < ARRAY_SIZE_X; indx )
{
float x = X_MIN - (indx - ARRAY_SIZE_X) * STEP_SIZE;
for (int indy = 0; indy < ARRAY_SIZE_Y; indy )
{
float y = Y_MIN - (indy - ARRAY_SIZE_Y) * STEP_SIZE;
result[indx][indy] = func(x, y) < 0;
}
}
CodePudding user response:
I think you may have problem here,
func(x, y) < 0;
I think it should be,
func(x, y) <= 0;
in order to produce Boolean results.