I have a problem with my homework.
1) I should write the function SSS with inputs a, b and c. I need to output alpha, beta and gamma.
2) I should write the function SWS with inputs a, b, and gamma. And I need to output c, alpha and beta.
Here is my code:
#include <iostream>
#include <cmath>
#include <math.h>
#include <cstdio>
using namespace std;
double SSS_alpha(double a, double b, double c){
int bot1 = -2*b*c;
if(bot1==0.0){
return 0.0;
}
double alpha = acos((a*a-b*b-c*c)/bot1);
const double rad = 0.5729577951308232088;
return alpha*rad;
}
double SSS_beta(double a, double b, double c){
double bot2 = -2*c*a;
if(bot2==0.0){
return 0.0;
}
double beta = acos((b*b-c*c-a*a)/bot2);
const double rad = 0.5729577951308232088;
return beta*rad;
}
double SSS_gamma(double a, double b, double c){
double bot3 = -2*b*a;
if(bot3==0.0){
return 0.0;
}
double gamma = acos((c*c-a*a-b*b)/bot3);
const double rad = 0.5729577951308232088;
return gamma*rad;
}
double WSW_seite_c(double a, double b, double gamma){
double c_1 = (a*a+b*b-2*a*b*cos(gamma));
double c = sqrt(c_1);
return c;
}
int main(){
cout << SSS_alpha(5.0, 7.0, 8.0)<<endl;
cout <<SSS_beta(5.0, 7.0, 8.0)<<endl;
cout <<SSS_gamma(5,7,8)<<endl;
cout <<"Seite c: "<<WSW_seite_c(5, 7, 0.81)<<endl;
}
I can only return one argument in one function. And I have a lot of functions for task 1:for alpha, for beta, for gamma. And I don't know how I can write it in one function. I wrote only one function for finding c for task 2.
I am new to C++. I would be happy if you can help me.:)
Returning a struct or using a class Triangle as proposed are perfect solutions and it is what I generally use.
However, in some simple cases, returning more than one value through a tuple can be quite convenient.
I showed a simple "working" example below.
Note that I will generally avoid this kind of solution for more than 3 return objects, to avoid confusion.
#include <iostream>
#include <tuple>
std::tuple<double, double, double> f(double x, double y){
double a = x;
double b = x+y;
double c = x-y;
return std::make_tuple(a, b, c);
}
int main() {
double a, b, c;
std::tie (a, b, c) = f (1.0, 2.0);
std::cout << "a = " << a << "\n";
std::cout << "b = " << b << "\n";
std::cout << "c = " << c << "\n";
return 0;
}
I hope the code is self explaining.
The syntax can be simplified with C++17. I did not use these simplifications because my current compiler is not compatible!
This approach can be combined with the struct one, as one can return several structs through a tuple.
Edit: I just see that NathanOliver already mentioned the tuple possibility in a comment...
First you dont need cstdio if you include iostream which you should preferably do in C++ since cstdio is just the C library migrated to C++.
As for your problem it sounds like you need to pass the variables by value. Your favourite C++ Book should tell you that there are cases like yours, where you need to "return" more than one value. In that case you can pass pointers(C-Style) or the safer references to functions which kind of act like pointers.
So you actually would define your function as follows:
void SSS(double a, double b, double c, double & alpha, double & beta, double & gamma);
Or as stated by #Ripi2 pack the values in a struct and return a value of that type :
/* Thanks to NathanOliver in the comments */
struct Values {
double a;
double b;
double c;
};
Values SSS(double a, double b, double c) {
Values values;
/* Do stuff */
return values;
}
A struct will be the simplest way of doing what you want. You can also create a class, but it might be an overkill solution for a homework (they basically are the same, but see my comment thread to get my point of view on that matter).
a struct declaration goes like this :
struct containerName
{
int val_a;
double val_b;
//and so on : you put what ever you need
}
The struct then basically becomes a type you can use pretty much like int, double, bool etc.
Here's a nice reading on struct and how to use it
Yes, you can only return one object from a function. But you can have it return a compound object, like a struct or a class. Traditionally you use structs for data only objects, because that is what they were in C.
struct Triangle
{
double a;
double b;
double c;
};
Then you can return a Triangle object from a function. And access its members this way:
Triangle tri1; // first, create an instance of the struct
tri1.a = 5.0f; // assign a value to a member
It's good practice to choose meaningful names for your data types (just like with your variables) and always design the data types so that they represent what they are named.
To make the code more expressive you could take it further with a more object oriented approach. You could give the data type Triangle member functions which calculate its angles, so that you can "ask" the Triangle what its angles are.
(You should also name it a class at that point because it it is not a pure data structure anymore, but that is a matter of convention. in C++ structs and classes are almost the same.)
class Triangle
{
public:
// everything in this section can be accessed from outside
// this is a constructor. It is a special function that lets you create a Triangle
Triangle(double pa, double pb, double pc)
: a(pa), b(pb), c(pc) // initialize the members
{}
// getters for the private members (not needed but that way they can't directly be changed)
double get_a() const
{
return a;
}
double get_b() const
{
return b;
}
double get_c() const
{
return c;
}
double alpha() const;
double beta() const;
double gamma() const;
// should be const because they dont change anything about the object
private:
// the default access for classes, everything in this section can only be accessed by member functions
double a;
double b;
double c;
};
// member function definitions outside of class declaration
double Triangle::alpha() const
{
// calculate and return alpha...
}
double Triangle::beta() const
{
// calculate and return beta...
}
double Triangle::gamma() const
{
// ...
}
You can use this class this way:
int main()
{
// create a Triangle by calling the constructor
Triangle tri1(5.0, 7.0, 8.0);
std::cout << "Alpha: " << tri1.alpha() << std::endl;
std::cout << "Beta: " << tri1.beta() << std::endl;
std::cout << "Gamma: " << tri1.gamma() << std::endl;
return 0;
};
Related
I have a code similar to the minimal example below, where the function g is provided by a library and expects double (*)(double) as an argument. I cannot change this. The example code does not compile because the member has signature double (*C::)(double) as explained in e.g. this post, with a number of possible solutions.
#include <iostream>
double g(double (*f)(double x)) { return f(0); };
class C
{
public:
C(double b) { a = b; };
double f2() { return g(&f1); };
private:
double a;
double f1(double x) { return x + a; };
};
int main()
{
C c (1);
std::cout << c.f2() << std::endl;
return 0;
}
I wonder what the best way to implement this is given that I don't want to point to C::f1 outside the class but within another member function. As far as I understand, the member function C::f1 is not static since it is only fully known after an instance of the class is initialised. Since speed is also a concern: would this be a problem with any of the possible solutions proposed elsewhere for similar versions of this issue?
Make your f1 function static:
static double f1(double x) { return x + a; };
This gives it the same signature as what your g function expects. Since a static function does not have a hidden this pointer, you will have to find some other way to get the value of a into it.
Okay, based on the comments and ideas from the post mentioned before, I will suggest to change g as follows and add a wrapper function f2_wrapper.
#include <iostream>
double g(double (*f)(double x, void *context), void *context)
{
return f(0, context);
};
class C
{
public:
C(double b) { a = b; };
double f1(double x) { return x + a; };
double f2();
private:
double a;
};
double f2_wrapper(double x, void* context)
{
C *c = (C*) context;
return c->f1(x);
}
double C::f2() { return g(&f2_wrapper, this); }
int main()
{
C c (1);
std::cout << c.f2() << std::endl;
return 0;
}
This is an example of the composition of classes. But my code doesn't show a correct answer. This program must calculate the length of the line segment in the coordinates of the two ends of the line segment!
I don't know what to do in the main function. this code consists of two classes.
#include <cmath>
#include <iostream>
using namespace std;
class point {
private:
float x;
float y;
public:
void setpoint(float abscissa, float ordinate) {
x = abscissa;
y = ordinate;
}
float getx() { return x; }
float gety() { return y; }
};
class LineSegment {
public:
float length() {
result = sqrt(pow(a.getx() - b.getx(), 2) + pow(a.gety() - b.gety(), 2));
return result;
}
void displayMessage() { cout << result; }
private:
float result;
point a;
point b;
};
int main() {
point a;
float q, s;
cout << "Enter two numbers for first point:\n";
cin >> q >> s;
a.setpoint(q, s);
point b;
float e, r;
cout << "Enter two numbers for second point:\n";
cin >> e >> r;
a.getx();
a.gety();
LineSegment pt;
pt.length();
pt.displayMessage();
return 0;
}
enter image description here
The a and b local variables of your main() function are unrelated to the a and b members of class LineSegment. You should give LineSegment a constructor by which you can convey the endpoints to it, or at minimum provide a method or methods by which the endpoints can be set after the fact. You must not attempt to compute the segment length before its endpoints are set.
Neither the member a nor the member b are initialized for pt. You need to initialize them or they are initialized using the default constructor of point which happens to not do any initialization resulting in undefined behavior.
You could e.g. pass the points to the constructor of LineSegment to fix this:
class LineSegment {
public:
LineSegment(const point& p1, const point& p2)
: a(p1), b(p2)
{}
...
};
...
LineSegment pt {a, b};
...
Note: I recommend adding a prefix to member variables. m_ is one option (i.e. you'd use m_a and m_b as member variable names). This way you avoid confusion like this and also avoid shadowing of variables assuming this is the only kind of variable using this prefix.
Edit: You also never call setpoint on b in main; you need to do this before passing the points to the constructor in the above snippet.
Here is your code, touched up to work:
#include <cmath>
#include <iostream>
// using namespace std; // CHANGED: Bad practice
class point {
private:
float x = 0.0f; // CHANGED: Add default member initialization
float y = 0.0f;
public:
point() = default; // CHANGED: Add default constructor
point(int abscissa, int ordinate) : x(abscissa), y(ordinate) {} // ADDED
void setpoint(float abscissa, float ordinate) {
x = abscissa;
y = ordinate;
}
float getx() const { return x; } // CHANGED: Mark getters as const
float gety() const { return y; }
};
class LineSegment {
public:
// CHANGED: Add constructor so you can actually build a LineSegment
LineSegment(point one, point two) : a(one), b(two) {}
// CHANGED: Made a one-liner
float length() const {
return sqrt(pow(a.getx() - b.getx(), 2) + pow(a.gety() - b.gety(), 2));
}
// void displayMessage() const { std::cout << result; } // CHANGED: Not
// needed
private:
// float result; // CHANGED: Does not need to stored
point a;
point b;
};
int main() {
float q, s;
std::cout << "Enter two numbers for first point:\n";
std::cin >> q >> s;
point a(q, s); // Can now directly initialize
float e, r;
std::cout << "Enter two numbers for second point:\n";
std::cin >> e >> r;
point b(e, r); // CHANGED: Actually put values into b
// a.getx(); // CHANGED: These do nothing
// a.gety();
LineSegment pt(a, b); // CHANGED: Actually put data into pt
std::cout << "\nLine Length: " << pt.length() << '\n'; // CHANGED: Make use
// of functions now
// available
return 0;
}
Your biggest issues were not initializing your objects correctly. point b was never given the values e and r, and LineSegment pt was never given any points.
Making those small changes and your code works as expected. Just using a simple example of (0, 0) and (1, 1) provides output of 1.41421, which is root-2, which is correct.
Update: Somehow related to how-is-stdfunction-implemented
The program inserts different function pointers (a multiplication from a struct, a divide as a function, and an add as lambda) into a vector and then calls the elements with the same arguments. Problems arise only from the struct.
It works well with std::function but I can not make it compile when using function pointers. Does anyone have a clue how to repair the program; or better, how does std::function works? If I use a static member function instead, the program becomes trivial (not included below).
#include <iostream>
#include <string>
#include <vector>
#include <functional>
struct mult {
double operator()(double a, double b) { return a * b; }
double fun(double a, double b) { return a * b; }
};
double add(double a, double b) {
return a + b;
}
using namespace std;
int main(){
using fnc = function<double(double, double)>;
vector<fnc> functions;
functions.push_back(mult{});
functions.push_back([](double a, double b) {return a / b; });
functions.push_back(add);
double a = 3, b = 4;
cout << "a=" << a << ", b=" << b << endl;
for (int i = 0; i < 3; ++i)
cout << functions[i](a, b) << endl;
cout << endl;
typedef double (*fp)(double, double);
fp funPtr;
vector<fp> functions1;
//functions1.push_back(mult{}); error
typedef double (mult::*mfp)(double, double);
mfp f = &mult::fun;
mult * obj = new mult;
cout << (obj->*f)(3, 4) << endl;// OK!
//functions1.push_back(mfp); ERROR!
//functions1.push_back(obj->*f); ERROR!
//functions1.push_back(&mult::fun); ERROR!
functions1.push_back([](double a, double b) {return a / b; });
functions1.push_back(add);
for (int i = 0; i < 2; ++i)
cout << functions1[i](a, b) << endl;
std::cout << "\npres enter to exit...";
int wait_key = getchar();
return 0;
}
Member functions have a hidden first parameter, which is the pointer to the object it is called on. So
double mult::operator()(double a, double b) { return a * b; }
is in fact (somewhat) equal to
double operator()(mult* this, double a, double b) {
return a * b;
}
So that's why you cannot add a mfp type object to a vector of type fp.
edit: what will work is
struct mult {
static double fun(double a, double b) { return a * b; }
};
fp f = &mult::fun;
functions1.push_back(f);
As by making a member function static, it's no longer tied to an object.
and
functions1.push_back(mfp);
is probably a typo anyway, since mfp was the typedef, and not the function object f...
edit 2: There is also the option to use std::bind to bind the first hidden parameter to a specific object.
E.g. using your original (non-static) member function:
mult obj;
fnc temp = std::bind(&mult::fun, &obj, std::placeholders::_1, std::placeholders::_2);
functions.push_back(temp);
I am implementing a particle-based fluid simulation. To represent vectors such as velocity, acceleration etc I have defined a class that looks like this
class Vec3f {
public:
float x, y, z;
// ... bunch of constructors, operators and utility functions
}
I'm using the library nanoflann for kd-tree searches. To accommodate for arbitrary class designs, nanoflann requires a user-defined adaptor class that the kd-tree class then queries to get info about the particle dataset. One function that the adaptor has to offer, as described in the nanoflann documentation is the following.
// Must return the dim'th component of the idx'th point in the class:
inline T kdtree_get_pt(const size_t idx, int dim) const { ... }
The problem is that this interface does not work seamlessly with the x, y, z representation. Naively, it would need to do something like this
inline float kdtree_get_pt(const size_t idx, int dim) const {
switch(dim) {
case 0:
return particlearray[idx].x;
case 1:
return particlearray[idx].y;
case 2:
return particlearray[idx].z;
}
}
Building and querying the kd-tree consumes a significant portion of my app's runtime and kd_tree_get_pt gets queried multiple times in the process so I need it to be optimized. The following solution should be faster.
class Vec3f {
public:
float values[3];
// ...
}
// Then inside the adaptor class
inline float kdtree_get_pt(const size_t idx, int dim) const {
return particlearrray[idx].values[dim];
}
However, I much prefer the x, y, z interface for my equations. Now that the problem is clear, my question is how can I keep the x, y, z notation for my equations without making kdtree_get_pt suboptimal.
Solutions I have considered:
Vec3f has member float values[3] and getters in the form of float& x(). The function call should be optimized away completely so this almost works but I do not want to have to add the parentheses in my equations if I can avoid it. eg I want to be able to write vec1.x - vec2.x instead of vec1.x() - vec2.x(). As far as I know, C++ does not offer a way to "disguise" a function call as a member variable, excluding preprocessor macros which I do not consider a safe solution.
Vec3f has members float values[3] and float& x, y, z where the latter are initialized to point to the corresponding floats in the array. I thought they would be optimized away as they are known at compile time and obviously cannot change value after initialization, but even with optimizations on, MSVC++ seems to actually store the float&s as can be seen by sizeof(Vec3f) growing by 12 bytes after their addition. This doubles the storage size of my dataset which raises a concern for cache misses when working with arbitrarily large datasets.
kdtree_get_pt uses float& values[3] to point to x, y, z. This might eliminate the branching cost, but I don't believe the extra level of indirection, nor the need to initialize all 3 references can be optimized away so it is presumably slower than the return particlearrray[idx][dim]` version.
kdtree_get_pt uses reinterpret_cast or pointer magic to directly point into Vec3f's members. Given a Vec3f object's address, I believe x, y, z are guaranteed to be stored in that order with the first one stored at the same address as the one given by the & operator on the Vec3f object, but even so I'm confused as to whether there exists a well-defined way to observe them.
From a software engineering standpoint, it's best to expose the data through accessor and modifier functions only.
I would suggest:
class Vec3f
{
public:
float& operator[](size_t index) { return values[index]; }
float operator[](size_t index) const { return values[index]; }
float& x() { return values[0]; }
float x() const { return values[0]; }
float& y() { return values[1]; }
float y() const { return values[1]; }
float& z() { return values[2]; }
float z() const { return values[2]; }
private:
float values[3];
}
Re: kdtree_get_pt uses reinterpret_cast or pointer magic to directly point into Vec3f's members.
That's a bad idea in general. However, I don't see that being a problem with my suggestion.
You should always check if the switch statements will really introduce branchings in the final compiled output. A tool that might help you there is godbolt.
For both of those code snippets (random and cout have been added to prevent complete removeal of the code):
#include<cstddef>
#include<array>
#include<iostream>
#include <ctime>
class Vec3f {
public:
float values[3];
};
struct Test {
std::array<Vec3f,100> particlearray;
float kdtree_get_pt(const size_t idx, int dim) const {
return particlearray[idx].values[dim];
}
};
int main() {
Test t;
std::srand(std::time(0));
int random_variable = std::rand();
std::cout << t.kdtree_get_pt(random_variable,0);
std::cout << t.kdtree_get_pt(random_variable,1);
std::cout << t.kdtree_get_pt(random_variable,2) << std::endl;
return 0;
}
and
#include<iostream>
#include<array>
#include<ctime>
#include<cstdlib>
#include<cstddef>
class Vec3f {
public:
float x, y, z;
};
struct Test {
std::array<Vec3f,100> particlearray;
float kdtree_get_pt(const size_t idx, int dim) const {
switch(dim) {
case 0:
return particlearray[idx].x;
case 1:
return particlearray[idx].y;
case 2:
return particlearray[idx].z;
}
}
};
int main() {
Test t;
std::srand(std::time(0));
int random_variable = std::rand();
std::cout << t.kdtree_get_pt(random_variable,0);
std::cout << t.kdtree_get_pt(random_variable,1);
std::cout << t.kdtree_get_pt(random_variable,2) << std::endl;
return 0;
}
The access to x, y and z or values[dim] will be compiled (by gcc 7) to:
cvtss2sd xmm0, DWORD PTR [rsp+rbx]
cvtss2sd xmm0, DWORD PTR [rsp+4+rbx]
cvtss2sd xmm0, DWORD PTR [rsp+8+rbx]
Without any branching.
There is known technique for mixing up access via x, y, z and array indices using union of identical data types. Resolves problem with UB, sizeof() is 12 bytes, access time is as fast as it can be, one could use SIMD vector in very similar fashion. Code below tested with VS2017
#include <iostream>
#include <type_traits>
template <int Size> struct VectorBase {
float _data[Size];
float operator[](int Index) {
return _data[Index];
}
};
template <typename VectorType, int Index> struct ScalarAccessor {
VectorType _v;
operator float() const {
return _v._data[Index];
}
float operator = (float x) {
_v._data[Index] = x;
return *this;
}
};
union uuu {
VectorBase<3> xyz;
ScalarAccessor<VectorBase<3>, 0> x;
ScalarAccessor<VectorBase<3>, 1> y;
ScalarAccessor<VectorBase<3>, 2> z;
};
template <int Size> struct Vector {
union
{
VectorBase<3> xyz;
ScalarAccessor<VectorBase<3>, 0> x;
ScalarAccessor<VectorBase<3>, 1> y;
ScalarAccessor<VectorBase<3>, 2> z;
};
float operator[](int Index) {
return xyz[Index];
}
};
using Vec3f = Vector<3>;
int main() {
Vec3f a;
a.x = 1.0f;
a.y = a.x + 3.0f;
a.z = a.x * 3.0f;
std::cout << sizeof(a) << "\n";
std::cout << a.x << " " << a.y << " " << a.z << "\n";
std::cout << a[0] << " " << a[1] << " " << a[2] << "\n";
std::cout << std::is_standard_layout<VectorBase<3>>::value << "\n";
std::cout << std::is_standard_layout<ScalarAccessor<VectorBase<3>, 0>>::value << "\n";
std::cout << std::is_standard_layout<ScalarAccessor<VectorBase<3>, 1>>::value << "\n";
std::cout << std::is_standard_layout<ScalarAccessor<VectorBase<3>, 2>>::value << "\n";
std::cout << std::is_standard_layout<Vec3f>::value << "\n";
std::cout << std::is_standard_layout<uuu>::value << "\n";
return 0;
}
UPDATE
Here some C++ standard reading
I'm relying on the definition of standard-layout type 12.7 Classes
A class S is a standard-layout class if it:
(7.1) — has no non-static data members of type non-standard-layout class (or array of such
types) or reference,
(7.2) — has no virtual functions (13.3) and no virtual base classes (13.1),
(7.3) — has the same access control (Clause 14) for all non-static data members,
(7.4) — has no non-standard-layout base classes, (7.5) — has at most one base class subobject of any given type
...
It is easy to check if all proposed classes are standard-layout - I've changed the code to check for that.
They are all layout-compatible, I believe
Also If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member.
Union is a standard-layout class as well, so we have classes aligned in union with only data member being array of the same type and size, and looks like standard requires it to be byte-by-byte compatible
However, I much prefer the x, y, z interface for my equations. Now that the problem is clear, my question is how can I keep the x, y, z
Declare x,y,z as local references before calculation:
auto& [x1, y1, z1] = v1.values;
auto& [x2, y2, z2] = v2.values;
return x1*x2 + y1*y2 + z1*z2;
For pre-C++17, you need more verbose:
auto& x = values[0];
auto& y = values[1];
auto& z = values[2];
The compiler will not need to use any storage for these references.
This of course introduces some repetition; One line (in C++17) per vector per function.
Extra parentheses introduced by your first suggestion is another good way to go. Whether the introduction of parentheses is better or worse than local reference declaration boiler plate depends on the use case and personal preference.
Edit: Another alternative: Define operator[] and use named constants for indices.
namespace axes {
enum axes {
x, y, z
};
}
struct Vec3f {
float values[3];
float& operator[](size_t index) { return values[index]; }
float operator[](size_t index) const { return values[index]; }
};
// usage
using namespace axes;
return v1[x]*v2[x] + v1[y]*v2[y] + v1[z]*v2[z];
I have on situation, where i need to keep the value float as well as int. so tried like below. but no help. can any one help on this?
union Val {
int a;
float b;
};
Val p;
p.b = 45.56;
int k = p.a; // i want k should be 45;
I see that you say:
i dont want each time it to be converted from float to int [sic]
To do that you could use user-defined conversions to accomplish this.
So your struct would look like this:
class Val {
int a;
float b;
public:
Val& operator= (const int _a) {a = _a; b = _a + fmod(b, 1.0F); return *this;}
Val& operator= (const float _b) {b = _b; a = trunc(_b); return *this;}
operator int() {return a;}
operator float() {return b;}
};
Please note that what you really want to use is simply a float with static_cast<int> For astatic_cast:
No checks are performed during runtime to guarantee that the object being converted is in fact a full object of the destination type. Therefore, it is up to the programmer to ensure that the conversion is safe. On the other side, it does not incur the overhead of the type-safety checks of dynamic_cast.
I've provided an example of using Val here: http://ideone.com/XUesib but you could accomplish the exact same thing given float foo like this:
foo = 1.3F;
cout << static_cast<int>(foo) << endl << foo << endl;
foo = 13 + fmod(foo, 1.0F);
cout << static_cast<int>(foo) << endl << foo << endl;
I have on situation, where i need to keep the value float as well as int. so tried like below
You can't do it with a union. A union can only hold a single value inside at any time. You need two separate variables. You can keep them in side a struct if you like:
struct Val {
int a;
float b;
};
Now you can have both an int and a float.
Val p;
p.b = 45.56;
p.a = p.b;
int k = p.a; // no conversion
That said, since you apparently only use a to store a converted value of b, you should measure whether the conversions even affect performance.
You can use structure with constructor, and initialize your variables in it as you wish.
struct Val {
int a;
float b;
Val(float value) {
a = b = value;
}
};
So you can use it in loop and don't worry about conversations each time, just create your Val variable outside loop and use it.