C++ Array not sorting properly - c++

I wanted to sort nuggets by unit price, so I made a class Nugget with the variables quant, and price, then made a double unit, which is price/quant. The nuggets come in 4, 6 and 9 packs
When I input 10, 10, and 10, for the price of each, I should get a sorted array of 9pack, 6pack and then a 4pack, because 10/9 is less than 10/6 and 10/4. But thats not the case.
#include <iostream>
using namespace std;
class Nugget {
public:
int price;
int quant;
double unit;
Nugget(int price, int quant) {
this->price = price;
this->quant = quant;
this->unit = price/quant;
}
};
int main(){
int n4,n6, n9;
cin >> n4 >> n6 >> n9;
Nugget* nuggetArr[3] = {new Nugget(n4,4), new Nugget(n6,6), new Nugget(n9,9)};
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (nuggetArr[j]->unit > nuggetArr[i]->unit) {
Nugget* temp = nuggetArr[i];
nuggetArr[i] = nuggetArr[j];
nuggetArr[j] = temp;
}
}
for (int j = 0; j < 3; j++)
cout << nuggetArr[j]->quant << ' ';
cout << endl << endl;
}
for (int i = 0; i<3; ++i)
cout << nuggetArr[i]->quant << ' ';
return 0;
};

What sorting algorithm you want to use?
If you swap nuggetArr[i] for nuggetArr[j] you should ensure that i < j for ascending or i > j for descending order.
For example:
for (int i = 0; i < 3; ++i) {
for (int j = i + 1; j < 3; ++j) {
if (nuggetArr[j]->unit > nuggetArr[i]->unit) {
Nugget* temp = nuggetArr[i];
nuggetArr[i] = nuggetArr[j];
nuggetArr[j] = temp;
}
}
Your code moves around objects (nuggets) not keeping some order.
For example you swap nuggetArr[1] for nuggetArr[2] and then nuggetArr[2] for nuggetArr[1].
FYI this is similar to Selection sort.

C++ uses a wierd way of casting here. It uses integers until assignement, so the unit value will be an integer even though you used double. If you make the following changes you will find that it will work (Please note that this is just to illustrate the point and is not good to use this because of precision):
...
double price;
double quant;
...
this->unit = this->price/this->quant;
...
Hope this helps
To be more precise as a note if a,b are integers then a/b will be an integer by default and after the division will it only be cast as a double.

Related

Code running time varies according to data input

I wrote a code to calculate moving L2 norm of two arrays.
func_lstl2(const int &nx, const float x[],const int &ny, const float y[], int &shift, double &lstl2)
{
int maxshift = 200;
int len_z = maxshift * 2;
int len_work = len_z + ny;
//initialize array work and array z
double *z = new double[len_z]; float *work = new float[len_work];
for (int i = 0; i < len_z; i++)
z[i] = 0;
for (int i = 0; i < len_work; i++)
work[i] = 0;
for (int i = 0; i < ny; i++)
work[i + maxshift] = y[i];
// do moving least square residue calculation
float temp;
for (int i = 0; i < len_z; i++)
{
for (int j = 0; j < nx; j++)
{
temp = x[j] - work[i + j];
z[i] += temp * temp;
}
}
// find the best fit value
lstl2 = 1E30;
shift = 0;
for (int i = 0; i < len_z; i++)
{
if (z[i] < lstl2)
{
lstl2 = z[i];
shift = i - maxshift;
}
}
//end of program
delete[] z;
delete[] work;
}
I tested two arrays with exactly same length and same scale.
int shift; double lstl2;
func_lstl2(2000,z1,2000,z2,shift,lstl2) ;
func_lstl2(2000,x1,2000,x2,shift,lstl2) ;
For z array, it used 0.0032346 seconds, for x array, it used 0.0140903 seconds. I cannot figure out why there is near 5 times time consumption difference. Could you help me figure it out? Thank you very much!
Here is the link for z array and x array.
https://drive.google.com/file/d/1aONKTjE_7NI1bp8YkDL2CMfg9C5h67Fe/view?usp=sharing
I strongly suspect you're dealing with denormalized floating point calculation effects. Using your existing function, loading the values as-appropriate in vectors, and turning them loose seven times on the provided input, (compiled with -O3 optimization)
for (int i = 0; i < 5; ++i)
{
int shift = 0;
double lstl2 = 0;
auto tp0 = steady_clock::now();
func_lstl2(2000, v1.data(), 2000, v2.data(), shift, lstl2);
auto tp1 = steady_clock::now();
std::cout << pr[0] << ',' << pr[1] << ':';
std::cout << duration_cast<milliseconds>(tp1 - tp0).count() << "ms\n";
}
I receive the following output, confirming your conundrum:
x1.txt,x2.txt:23ms
x1.txt,x2.txt:19ms
x1.txt,x2.txt:21ms
x1.txt,x2.txt:21ms
x1.txt,x2.txt:19ms
x1.txt,x2.txt:22ms
x1.txt,x2.txt:21ms
z1.txt,z2.txt:8ms
z1.txt,z2.txt:9ms
z1.txt,z2.txt:5ms
z1.txt,z2.txt:5ms
z1.txt,z2.txt:6ms
z1.txt,z2.txt:5ms
z1.txt,z2.txt:5ms
However, enabling denormalize-as-zero (DAZ) and flush-to-zero (FTZ) for floating calculations (the mechanism for doing so is toolchain-dependent; below is clang 13.01 on macOS):
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
delivers the following:
x1.txt,x2.txt:4ms
x1.txt,x2.txt:4ms
x1.txt,x2.txt:3ms
x1.txt,x2.txt:5ms
x1.txt,x2.txt:3ms
x1.txt,x2.txt:3ms
x1.txt,x2.txt:5ms
z1.txt,z2.txt:7ms
z1.txt,z2.txt:6ms
z1.txt,z2.txt:4ms
z1.txt,z2.txt:3ms
z1.txt,z2.txt:3ms
z1.txt,z2.txt:4ms
z1.txt,z2.txt:3ms
Your x-data set is sensitive to this; z does not appear to be. See this question for a better explanation.

Replacing the value of map elements isnt working

I'm just Learning about std::map and its functions . I recently got this problem. I tried making a program which prints out a grid type data where I used std::map for the keys and values . The program prints out fine but I wanted to make a program where once I erased a data in that grid, other data above that should move down one step and the topmost would have 0 in it . somehow I tried but it doesn't seem to work . I don't know where I did wrong in that . My code:
in class header:
#pragma once
#include<iostream>
#include<string>
#include<vector>
#include<map>
#define x_Pair std::pair<unsigned int,unsigned int>
class MapCheck
{
public:
std::map<x_Pair, unsigned int>m_MapData;
void SetMapData();
x_Pair GetBlockCell(int num);
void EraseCell(int cell);
};
in class cpp:
void MapCheck::SetMapData()
{
int count = 1;
for (int j = 0; j < 20; j++)
{
for (int i = 0; i < 10; i++)
{
m_MapData[{i, j}] = count;
count++;
}
}
}
x_Pair MapCheck::GetBlockCell(int num)
{
for (int j = 0; j < 20; j++)
{
for (int i = 0; i < 10; i++)
{
if (m_MapData[{i, j}] == num)
{
return x_Pair(i, j);
}
}
}
return x_Pair(-1, -1);
}
void MapCheck::EraseCell(int cell)
{
x_Pair pair = GetBlockCell(cell);
for (int i = pair.second; i < 20; i++)
{
m_MapData[{pair.first, i}] = m_MapData[{pair.first, i - 1}];
m_MapData[{pair.first, i - 1}] = 0;
}
}
-and in main:
#include"MapCheck.h"
int main()
{
MapCheck mc;
mc.SetMapData();
std::string input;
do
{
system("cls");
for (int j = 0; j < 20; j++)
{
for (int i = 0; i < 10; i++)
{
std::cout << mc.m_MapData[{i, j}] << " ";
}
std::cout << std::endl;
}
std::cout << "Enter a number to erase or E to exit";
std::cin >> input;
mc.EraseCell(std::atoi(input.c_str()));
} while (input != "E");
return 0;
}
the output without any inputs :
after entering number 191 in the input :
expected result:
All Except the printing is fine . I dont Get Where I did Wrong. Any help would be appreciated. Thanks in advance!!
The order of
for (int i = pair.second; i < 20; i++)
{
m_MapData[{pair.first, i}] = m_MapData[{pair.first, i - 1}];
m_MapData[{pair.first, i - 1}] = 0;
}
is element found to the bottom. When you want to move everything above the item removed down one slot, this isn't all that useful. So lets flip it around.
for (int i = pair.second; i > 0; i--)
{
m_MapData[{pair.first, i}] = m_MapData[{pair.first, i - 1}];
}
m_MapData[{pair.first, 0}] = 0;
This starts at the item being removed and goes up to slot 1, copying each item down one slot. To handle the top of the column, we have m_MapData[{pair.first, 0}] = 0; to set the top item to zero, something we only need to do once.
Side note: Unless we have a sparse array, this would be a lot more efficient with a 2D array in place of the map.
You have following:
x_Pair MapCheck::GetBlockCell(int num)
which is used as
x_Pair pair = GetBlockCell(cell);
This will invoke copy constructor of std::pair<>.
I think you need to return and use reference:
x_Pair& MapCheck::GetBlockCell(int num)
which is used as
x_Pair& pair = GetBlockCell(cell);

C6385 warning in VS (in regard to dynamic arrays)

My code is supposed to print the Union and Intersection of two sets of integers.
Why do I get this warning?
Is it because I use dynamic arrays and it's size could be anything in runtime?
How can I fix it? My code works fine but this warning really bugs me.
P.S: I know it would be a lot easier to use std::vector but my teacher required to use arrays.
#include <iostream>
using namespace std;
void UnionFunc(int[],int,int[],int,int[],int&);
void IntersectionFunc(int[], int, int[], int, int[], int&);
int main() {
int* A;
int SizeA;
int* B;
int SizeB;
int* Union;
int UnionSize=0;
int* Intersection;
int IntersectionSize=0;
cout << "Enter the Size of First Set : "; cin >> SizeA;
A = new int[SizeA];
cout << "Enter the Size of Second Set : "; cin >> SizeB;
B = new int[SizeB];
Intersection = new int[SizeA >= SizeB ? SizeB : SizeA];
Union = new int[SizeA + SizeB];
for (int i = 0; i < SizeA; i++) {
cout << "Set A[" << i + 1 << "] = ";
cin >> A[i];
}
for (int i = 0; i < SizeB; i++) {
cout << "Set B[" << i + 1 << "] = ";
cin >> B[i];
}
UnionFunc(A,SizeA,B,SizeB,Union,UnionSize);
IntersectionFunc(A, SizeA, B, SizeB, Intersection, IntersectionSize);
cout <<endl<< "Union Set : ";
for (int i = 0; i < UnionSize; i++) {
cout << Union[i] << ",";
}
cout <<endl <<"Intersection Set : ";
for (int i = 0; i < IntersectionSize; i++) {
cout << Intersection[i] << ",";
}
system("pause>n");
return 0;
}
void UnionFunc(int A[],int SizeA, int B[],int SizeB, int Union[],int &UnionSize) {
//Adding First Array to Union Array
for (int i = 0; i < SizeA;i++) {
Union[i] = A[i];
UnionSize++;
}
//Checking if second array's elemnts already exist in union arry, if not adding them
bool exist;
for (int i = 0; i < SizeB; i++) {
exist = false;
for (int j = 0; j < UnionSize; j++) {
if (B[i] == Union[j] ) {
exist = true;
}
}
if (exist == false) {
Union[UnionSize] = B[i];
UnionSize++;
}
}
}
void IntersectionFunc(int A[], int SizeA, int B[], int SizeB, int Intersection[], int& IntersectionSize) {
for (int i = 0; i < SizeA; i++) {
for (int j = 0; j < SizeB; j++) {
if (A[i] == B[j]) {
Intersection[IntersectionSize] = A[i];
IntersectionSize++;
}
}
}
}
Is it because I use dynamic arrays and it's size could be anything in
runtime?
Yes! The compiler doesn't know (and, as your code is written, can't know) that both SizeA and SizeB will be 'valid' numbers - so the size of the three int arrays you create could be less than is required for the Intersection[i] 'read' to be valid.
A 'quick and dirty' fix for this is to provide a visible guarantee to the compiler that the arrays you create will be at least a certain size, like this:
A = new int[max(1,SizeA)]; // Compiler can now 'see' a minimum size
And similarly for the other allocations you make with the new[] operator.
(I have tested this with VS2019, adding the max(1,SizeA) and max(1,SizeB) 'fixes' to just the allocations of A and B and the warning is removed.)

Trying to implement Durand-Kerner-Method in C++ using Matrices

My implementation of the Durand-Kerner-Method (https://en.wikipedia.org/wiki/Durand%E2%80%93Kerner_method) does not seem to work. I believe (see following code) that I am not calculating new approximation correctly in the algorithm part itself. I cannot seem to be able to fix the problem. Very grateful for any advice.
#include <complex>
#include <cmath>
#include <vector>
#include <iostream>
#include "DurandKernerWeierstrass.h"
using namespace std;
using Complex = complex<double>;
using vec = vector<Complex>;
using Matrix = vector<vector<Complex>>;
//PRE: Recieves input value of polynomial, degree and coefficients
//POST: Outputs y(x) value
Complex Polynomial(vec Z, int n, Complex x) {
Complex y = pow(x, n);
for (int i = 0; i < n; i++){
y += Z[i] * pow(x, (n - i - 1));
}
return y;
}
/*PRE: Takes a test value, degree of polynomial, vector of coefficients and the desired
precision of polynomial roots to calculate the roots*/
//POST: Outputs the roots of Polynomial
Matrix roots(vec Z, int n, int iterations, const double precision) {
Complex z = Complex(0.4, 0.9);
Matrix P(iterations, vec(n, 0));
Complex w;
//Creating Matrix with initial starting values
for (int i = 0; i < n; i++) {
P[0][i] = pow(z, i);
}
//Durand Kerner Algorithm
for (int col = 0; col < iterations; col++) {
*//I believe this is the point where everything is going wrong*
for (int row = 0; row < n; row++) {
Complex g = Polynomial(Z, n, P[col][row]);
for (int k = 0; k < n; k++) {
if (k != row) {
g = g / (P[col][row] - P[col][k]);
}
}
P[col][row] -= g;
}
return P;
}
}
The following Code is the code I am using to test the function:
int main() {
//Initializing section
vec A = {1, -3, 3,-5 };
int n = 3;
int iterations = 10;
const double precision = 1.0e-10;
Matrix p = roots(A, n, iterations,precision);
for (int i = 0; i < iterations; i++) {
for (int j = 0; j < n; j++) {
cout << "p[" << i << "][" << j << "] = " << p[i][j] << " ";
}
cout << endl;
}
return 0;
}
Important to note the Durand-Kerner-Algorithm is connected to a header file which is not included in this code.
Your problem is that you do not transcribe the new values into the next data record with index col+1. Thus in the next loop you start again with a data set of zero entries. Change to
P[col+1][row] = P[col][row] - g;
If you want to use the new improved approximation immediately for all following approximations, then use
P[col+1][row] = (P[col][row] -= g);
Then the data sets all contain the next approximations, especially the first one will no longer contain the initially set powers.

The most occuring number in structure(array)

I cant find out whats wrong with this part of my program, i want to find out most occuring number in my structure(array), but it finds only the last number :/
void Daugiausiai(int n)
{
int max = 0;
int sk;
for(int i = 0; i < n; i++){
int kiek = 0;
for(int j=0; j < n; j++){
if(A[i].datamet == A[j].datamet){
kiek++;
if(kiek > max){
max = kiek;
sk = A[i].datamet;
}
}
}
}
}
ps. its only a part of my code
You haven't shown us enough of your code, but it is likely that you are not looking at the real result of your function. The result, sk is local to the function and you don't return it. If you have global variable that is also named sk, it will not be touched by Daugiausiai.
In the same way, you pass the number of elements in your struct array, but work on a global struct. It is good practice to "encapsulate" functions so that they receive the data they work on as arguments and return a result. Your function should therefore pass both array length and array and return the result.
(Such an encapsulation doesn't work in all cases, but here, it has the benefit that you can use the same function for many different arrays of the same structure tape.)
It is also enough to test whether the current number of elements is more than the maximum so far after your counting loop.
Putting all this together:
struct Data {
int datamet;
};
int Daugiausiai(const struct Data A[], int n)
{
int max = 0;
int sk;
for (int i = 0; i < n; i++){
int kiek = 0;
// Count occurrences
for(int j = 0; j < n; j++){
if(A[i].datamet == A[j].datamet) kiek++;
}
// Check for maximum
if (kiek > max) {
max = kiek;
sk = A[i].datamet;
}
}
return sk;
}
And you call it like this:
struct Data A[6] = {{1}, {2}, {1}, {4}, {1}, {2}};
int n = Daugiausiai(A, 6);
printf("%d\n", n); // 1
It would be nice if you had english variable names, so I could read them a bit better ^^. What should your paramter n do? Is that the array-length? And what should yout funtion do? It has no return value or something.
int getMostOccuring(int array[], int length)
{
int current_number;
int current_count = 0;
int most_occuring_number;
int most_occuring_count = 0;
for (int i = 0; i < length; i++)
{
current_number = array[i];
current_count = 0;
for (int j = i; j < length; j++)
{
int test_number = array[j];
if (test_number == current_number)
{
current_count ++;
if (current_count > most_occuring_count)
{
most_occuring_number = current_number;
most_occuring_count = current_count;
}
}
}
}
return most_occuring_number;
}
this should work and return the most occuring number in the given array (it has a bad runtime, but is very simple and good to understand).