Large Numbers Division returns 1 [c++] - c++

I am new here so i am sorry if my question is a kind stupid, but, i was calculating the divisions of two large numbers and storing them in an array, like this:
int det(double M[25][25], int m)
{
/*returns large numbers*/
}
int main()
{
float y[27];
double A[25][25] = {0}, N = 26, D = -134430487042201894894174208;
y[0] = 0;
y[26] = 1;
for (int i = 0; i < N-1; i++)
{
//Reset A[][] to the original
for (int k = 0; k < N-1; k++)
{
for (int J = 0; J < N-1; J++)
{
A[k][J] = m[k][J];
}
}
//Change values of A[j][i]
for (int j = 0; j < N-1; j++)
{
A[j][i] = d[j+1];
}
y[i+1] = det(A,N-1)/D; //Here y returns only 0, 1, 1, 1, 1, ...
}
}D
So, what am i doing wrong? y array returns 0, 1, 1, 1, 1, ... , and it was supposed to not be 1
det(A,N-1) = 7958284334509567005163520
D = -134430487042201894894174208
det(A,N-1)/D = -0.05919999629259109195883585509348322869497780932400145347...
It's not 1.
Thanks!

The function det is returning an int. You are never going to get floating point values from it.

Related

how to fill array with contents of another array that has different size using loops

I am trying to fill an array sized by [4344][20] with the contents of other array sized by [5430][20]. I wrote the following code and it has no errors. It filled the X_train correctly, but the Y_train didn't filled successfully. it remained zeros as its initialized.
my code:
void split(int fold, int array_X_set[5430][20], int array_Y_set[5430],
int X_train[4344][20], int Y_train[4344],
int X_test[1086][20], int Y_test[1086])
{
int rows = 5430;
int cols = 20;
int division = 1086;
int nTest = 0, nTrain = 0, nTest1 = 0, nTrain1 = 0;
switch (fold) {
case 1:
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (i < division) {
X_test[nTest][nTest1] = array_X_set[i][j];
Y_test[nTest] = array_Y_set[i];
nTest1++;
}
else {
X_train[nTrain][nTrain1] = array_X_set[i][j];
Y_train[nTrain] = array_Y_set[i];
nTrain1++;
}
}
}
break;
another condition :
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (i >= 1086 && i <= 2171) {
X_test[i][j] = array_X_set[i][j];
Y_test[i] = array_Y_set[i];
}
else {
X_train[i - division][j] = array_X_set[i][j];
Y_train[i - division] = array_Y_set[i];
}
}
}
you can try this code, so that you don't need extra variable like nTest, nTrain, nTest1, nTrain1.
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (i < division) {
X_test[i][j] = array_X_set[i][j];
Y_test[i] = array_Y_set[i];
} else {
X_train[i-division][j] = array_X_set[i][j];
Y_train[i-division] = array_Y_set[i];
}
}
}
updated:
Another condition:
if you have 10 elements in array
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
^ ^ ^ ^
you want to put index 3~6 to new array, in new array, its index would be 0~3
so for the part >=3 && <=6 would be newArr[i-3] = originalArr[i]
and if you want to put index 0~2 and 7~9 to new array, in new array, its index would be 0~2 and 3~5
so for the part <3 would be newArr[i] = originalArr[i]
the part >6 would be newArr[i-(6-3+1)] = originalArr[i], (6-3+1) means the element count between the part >=3 && <=6
Here is the code in your condition:
(>=1086 && <=2171 in test array, <1086 || >2172 in train array)
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (i >= 1086 && i <= 2171) {
X_test[i - 1086][j] = array_X_set[i][j];
Y_test[i - 1086] = array_Y_set[i];
}
else {
if(i<1086){
X_train[i][j] = array_X_set[i][j];
Y_train[i] = array_Y_set[i];
}else{
X_train[i - (2171-1086+1)][j] = array_X_set[i][j];
Y_train[i - (2171-1086+1)] = array_Y_set[i];
}
}
}
}

C++: Reshape vector to 3D array

Edit: I have uploaded the vector to Drive as a text file, in case anyone want to have a look: https://drive.google.com/file/d/0B0wsPU8YebRQbDUwNFYza3ljSnc/view?usp=sharing
I'm trying to reshape my vector h into a 3D array. h contains 295788 elements. In this case height = 314, width = 314 and depth = 3.
Basically what I'm trying to do is what MATLAB does with its reshape function.
h = reshape(h, height, width, depth)
This is my attempt so far, but when I print it all I see is zeroes, which is not right. I have double checked that h contains the numbers I'm expecting.
vector<vector<vector<double> > > array3D;
int height = 314, width = 314, depth = 3;
// Set up sizes
array3D.resize(height);
for (int i = 0; i < height; ++i) {
array3D[i].resize(width);
for (int j = 0; j < width; ++j)
array3D[i][j].resize(depth);
}
for (int i = 0; i < height; i++)
{
array3D[i][0][0] = h[i];
for (int j = 0; j < width; j++)
{
array3D[i][j][0] = h[i+j];
for (int k = 0; k < depth; k++)
{
array3D[i][j][k] = h[i+j+k];
}
}
}
Printing:
for (vector<vector<vector<double>>>::const_iterator i = array3D.begin(); i != array3D.end(); ++i)
{
for (vector<vector<double>>::const_iterator j = i->begin(); j != i->end(); ++j)
{
for (vector<double>::const_iterator k = j->begin(); k != j->end(); ++k)
{
cout << *k << ' ';
}
}
}
So my question is, how do I convert my vector into a 3D array properly?
I managed to do this by using Eigen::Tensor as suggested by Henri Menke. I ended up creating an array for the initial 314x314x3 matrix, and then another one for the 300x300x3 matrix. It's neither fast nor pretty, but for now that is what I could come up with. Looks like this.
For clarification: margin is calculated further up in the code, but in this example with the 314x314x3 matrix it's margin=7. h is a vector with 295788 elements. nrh=314, nch=314 and nradii=3.
Tensor<int, 3> t(nrh, nch, nradii);
int counter = 0;
for (int k = 0; k < nradii; k++)
{
for (int col = 0; col < nch; col++)
{
for (int row = 0; row < nrh; row++)
{
t(row, col, k) = h[counter];
counter += 1;
}
}
}
int height = nrh - margin * 2;
int width = nch - margin * 2;
int depth = nradii;
Tensor<int, 3> out(height, width, depth);
int count1 = 0, count2 = 0, count3 = 0;
for (int k = 0; k < depth; k++)
{
for (int j = margin; j < nch - margin; j++)
{
for (int i = margin; i < nrh - margin; i++)
{
out(count1, count2, count3) = t(i, j, k);
count1 += 1;
}
count1 = 0;
count2 += 1;
}
count2 = 0;
count3 += 1;
}
Edit: Solution #2 with Tensor.slice()
int height = nrh - margin * 2;
int width = nch - margin * 2;
int depth = nradii;
Tensor<int, 3> tensor(height, width, depth);
DSizes<ptrdiff_t, 3> indices(margin, margin, 0);
DSizes<ptrdiff_t, 3> sizes(height, width, nradii);
tensor = t.slice(indices, sizes);
How about:
array3D[i][j][k] = h[i*(depth*width)+j*depth+k];
That may or may not be scanning the vector in the correct order.
Notice how when the index k resets the index j increments so you move on exactly one until the index j resets in which case i increments and the same. It's easy to show this calculation reads every element exactly once.
I'd normally expect a width, height then depth and you're scanning in the opposite order!
Footnote: Depending on the application is may be worthwhile to just access the vector using this approach. In general it turns out to be faster than accessing a vector of vectors of vectors. That can be relevant when dealing with massive arrays.
Actually, your the structure of your code is already ok, however, there are two mistakes:
The lines
array3D[i][0][0] = h[i];
and
array3D[i][j][0] = h[i+j];
are pointless. You are overwriting those entries later on with the line
array3D[i][j][k] = h[i+j+k];
The index calculation for h[] is wrong: You must multiply the row index by the length of a row before adding the cell index. The assignment should look like this:
array3D[i][j][k] = h[(i*width+j)*depth+k];
Otherwise, you will get the same result for (i, j, k) == (3, 2, 1) as for (i, j, k) == (1, 3, 2), which is obviously wrong. In the index calculation above, I have assumed that k is the fastest changing dimension. If that is not the order in which your data is stored in h, you need to change the positions of i, j, and k and adjust the factors accordingly.
Putting this together, your assignment loop should read:
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
for (int k = 0; k < depth; k++) {
array3D[i][j][k] = h[(i*width+j)*depth+k];
}
}
}
Slightly off-topic:
If you were using C instead of C++, you could "simply" do this:
size_t dataSize;
//Create a real 3D array with the dimensions (height, width, depth).
double (*array3D)[width][depth] = malloc(dataSize = height*sizeof(*array3D));
//Copy over the data from the file.
memcpy(array3D, h, dataSize);
//Print the array contents:
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
for (int k = 0; k < depth; k++) {
printf("%d ", array3D[i][j][k]);
}
}
}
This uses a real 3D array instead of an array of pointers to arrays of pointers to arrays of doubles (which is roughly what a vector<vector<vector<double>>> is). However, this cannot be done in C++ as C++ does not allow for array types with dynamic sizes as C does.

dealing with emxArray_real_T data in C++

I have converted a piece of code to C++ using Matlab and now have them in MSVC++.
My function: myFunction gets two inputs and has one output. Following, I tried to make the inputs, a, b, and allocate the output, but I got this error: error C3861: 'emxCreate_real_T': identifier not found
The function prototype looks like this, which in essence is C = A + B:
#include "myTestFunction.h"
#include "myTestFunction_emxutil.h"
void myTestFunction(const emxArray_real_T *A, const emxArray_real_T *B,
emxArray_real_T *C)
{
int i0;
int loop_ub;
i0 = C->size[0] * C->size[1];
C->size[0] = A->size[0];
C->size[1] = A->size[1];
emxEnsureCapacity((emxArray__common *)C, i0, (int)sizeof(double));
loop_ub = A->size[0] * A->size[1];
for (i0 = 0; i0 < loop_ub; i0++) {
C->data[i0] = A->data[i0] + B->data[i0];
}
}
and here is my main function:
int main() {
double a[3][3];
double b[2][2];
double result[4][4] = {};
emxArray_real_T *inpA, *inpB, *outp;
// define input matrix
double p = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++){
a[i][j] = p;
p = p + 1;
}
}
double k = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
b[i][j] = k;
k = k + 1;
}
}
inpA = emxCreateWrapper_real_T(*a, 3, 3);
inpB = emxCreateWrapper_real_T(*b, 2, 2);
outp = emxCreateWrapper_real_T(*result, 4, 4);
//inpA = emxCreate_real_T(a, 3, 3);
//inpB = emxCreate_real_T(b, 2, 2);
//outp = emxCreate_real_T(result, 4, 4);
myTestFunction(inpA, inpB, outp);
//print result
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++)
cout << outp[i].data[j] << endl;
}
return 0;
}
How should I declare the inputs and output?
You're missing an include file. Based on the link you provided in your comment, there is probably a myTestFunction_emxAPI.h file that needs to be included.
Also, I see that the b[2][2] array that you created is being accessed beyond its bounds by the for (int i = 0; i < 3; i++)' andfor (int j = 0; j < 3; j++)` loops.

better algorithm for counting points in grids

Suppose I have a point P in [0,1]*[0,1], and [0,1] is divided into m(say 200) grids. I use A[m][m] to indicate whether [a small square centred at P with length 2h] covers each grid or not. So for a point P, A[i][j] is either (increase by) 1 or 0.
Suppose I have n such points(P1,...,Pn), I want to calculate A(for each point Pi, I redo the above procedure, adding 1 or not). How can I do this efficiently(with C++) rather than writing 3 layers of for loops to check for each grid and each point(So O(nm^2))?
I tried the naive 3 for loops with C++. It takes longer time than using some of the vectorized operations(like vector<= number for comparing n numbers together, A[bool vector, bool vector] for subsetting) in R.
Since C++ is generally faster than R, is there any smart way to implement this process?
#include <Rcpp.h>
#include <cmath>
using namespace Rcpp;
// [[Rcpp::export]]
double myfun(NumericVector u, NumericVector v)
{
double n = u.size();
double A[200][200] = {0};
double pos[200];
int i = 0, j = 0, k = 0;
for (i = 0; i < 200; i++)
{
pos[i] = (double)i / 201;
}
for (k = 0; k < n; k++)
{
for (i = 0; i < 200; i++)
{
for (j = 0; j < 200; j++)
{
if ( (fabs(u[k] - pos[i]) <= h) && (fabs(v[k] - pos[j]) <=h ) )
{
A[i][j]++;
}
}
}
}
double s = 0, avg = 0;
for (i = 0; i <200; i++)
{
for (j = 0; j < 200; j++)
{
s += A[i][j];
}
}
avg = s / (200 * 200);
return (avg);
}
The two inner loops only determine index of the point in your grid. But you can compute the index directly:
int i = (int)(u[k]*200);
int j = (int)(v[k]*200);
You probably also need to check that i and j don't reach the index 200. This only happens though, when u[k] == 1.0 or v[k] == 1.0.
double n = u.size();
double A[200][200] = {0};
for (int k = 0; k < n; k++)
{
int i = (int)(u[k]*200);
int j = (int)(v[k]*200);
if (i == 200)
i = 199;
if (j == 200)
j = 199;
A[i][j]++;
}

Wordsearch with directions saved in int array

I'm trying to develop a wordsearch which finds the word "OIE" (indicating how many times appears), based in an integer unidimensional array that saves the directions (8), but I get strange errors when I run this (and incorrect outputs).
This is the code:
int arrf[8] = {0, -1, -1, -1, 0, 1, 1, 1};
int arrc[8] = {-1, -1, 0, 1, 1, 1, 0,-1};
char s[] = "OIE";
int main() {
int n, m;
while (cin >> n >> m) {
int res = 0;
vector<vector<char> > S(n, vector<char>(m));
for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) cin >> S[i][j];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
for (int d = 0; d < 8; ++d) {
bool trobat = true;
for (int h = 0; h < 3 and trobat; ++h) {
int f = i + arrf[d], c = j + arrc[d];
if (f < 0 || f >= n || c < 0 || c >= m || S[f][c] != s[h])
trobat = false;
}
if (trobat) res++;
}
}
}
cout << res << endl;
}
}
Could somebody help me to fix this? I would appreciate.
Regards.
One error is that this line
int f = i + arrf[d], c = j + arrc[d];
should be
int f = i + h*arrf[d], c = j + h*arrc[d];
With your code it doesn't matter how many times you go round the inner loop you are still checking the same position.