fix Compose's domain and some other minor issues in week 11 source#1
fix Compose's domain and some other minor issues in week 11 source#1haki-1 wants to merge 3 commits into
Conversation
|
|
||
| struct Product : public RealFunc | ||
| { | ||
| RealFunc *f, *g; |
There was a problem hiding this comment.
Хубаво е да са поне const, a най-добре и private - да не вземе някой да бърника :)
| std::cout << base->safeEval(3) << std::endl; | ||
| } | ||
|
|
||
| // problem with Compose's defined domain - example |
There was a problem hiding this comment.
Добре де, проблем има, а идея за решение 🤔?
|
|
||
| struct TanDomain : Set | ||
| { | ||
| bool check(float x) const override { return ceilf(x / (M_PI / 2)) != floorf(x / (M_PI / 2)) || (int)(x / (M_PI / 2)) % 2 == 0; } |
There was a problem hiding this comment.
Това не е ли малко дълго като за един ред 😆.
Освен това е доста криптично написано с тези условия - наложи се да го разпиша формално, за да разбера какво прави 😆
Наистина, опитай по-простичко да го изразиш - трябва просто да провериш дали x е от вида ½π + kπ, т.е. дали уравнението ½π + kπ = x има цяло решение за k.
Как да провериш дали k излиза цяло… ще се сетиш сам. Hint: използвай fmod от cmath.
И като работиш с плаваща запетая, е хубаво да допускаш някаква епсилон грешка. Иначе, формално, това е коректно :)
Week 11 Updates - unique pointers
| public: | ||
| ComposeSet(UniquePointer<RealFunc> a, UniquePointer<RealFunc> b) : a(a), b(b) {} | ||
|
|
||
| bool check(float x) const override { return a.ptr->getDomain().check(b.ptr->safeEval(x)); } |
There was a problem hiding this comment.
Измислил си го! Ама почти… трябва да провериш също, че x е в домейна на b, иначе може да гръмне вътрешното извикване :)
| UniquePointer(T const& other) : ptr(other.clone()) {} | ||
|
|
||
| UniquePointer(UniquePointer const& other) : ptr(new T(other.ptr)) {} | ||
| UniquePointer(UniquePointer const& other) : ptr(other.ptr->clone()) {} |
There was a problem hiding this comment.
Каква е идеята на тази промяна?
There was a problem hiding this comment.
Параметърът T приема T = Set или T = RealFunc, така в предходната реализация имаше new израз на интерфейс, а на интерфейс не можем да създаваме инстанции. При новата реализация виртуалният метод clone изпълнява new израз и създава обект на клас-наследник, който не е абстрактен.
There was a problem hiding this comment.
Хммм, да, прав си. То проблемът ни е, че изобщо дефинираме конструктор за копиране. По идея unique ptr е уникален, huh, и не би трябвало да предполага създаване на копия. Референцията на unique_ptr от стандартната библиотека дори го споменава изрично:
The class satisfies the requirements of MoveConstructible and MoveAssignable, but not the requirements of either CopyConstructible or CopyAssignable.
(виж, че дори няма дефиниран конструктор за копиране: https://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr)
Всъщност първия проблем, който аз видях в това, е че UniquePtr става зависим от това върху T да е дефиниран подходящ метод clone(), а ние искаме UniquePtr да е възможно най-общ.
Най-добре е в такъв случай да махнем изцяло този ред и да предадем задачата за копиране на извикващата страна, а вместо това да направим конструктор от чист указател UniquePointer::UniquePointer(T*).
| { | ||
| bool check(float x) const override | ||
| { | ||
| return fmod(x - M_PI / 2, M_PI) > eps || fmod(x - M_PI / 2, M_PI) < -eps; |
There was a problem hiding this comment.
Така е по-добре. А не можеш ли да комбинираш 2те условия в едно?
Насока: -e < x < e за положително епсилон е еквивалентно на |x| < e.
No description provided.