- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
这个问题是关于如何设计一个程序,这样就可以很容易地进行某些修改。
我有一个类,它包含一些(非平凡的)数据,并有几个更改这些数据的成员函数。
有时我需要计算此数据的某些属性。但是在每次更改时从头开始重新计算它是很慢的。相反,计算对这些属性的小更新要快得多。
我有几个这样的属性,我需要能够轻松地将它们添加到我的类中或从中删除(或打开/关闭)以进行一些数值实验。该类仅由我自己修改,用于数值模拟(科学代码)。
假设我有一个包含数字 x
的类。但我还需要 2^x
(x
的“属性”)。基础类是:
class C {
double x;
public:
C() : x(0.0)
{ }
void inc() { x += 1; }
void dec() { x -= 1; }
void set(double x_) { x = x_; }
};
但现在我需要跟踪 2^x
并在每次 x
更改时不断更新此值。所以我最终得到了
class expC {
double expx;
public:
expC(const double &x) {
recompute(x);
}
void inc() { expx *= 2; } // fast incremental change
void dec() { expx /= 2; } // fast incremental change
void recompute(const double &x) {
expx = std::pow(2, x); // slow recomputation from scratch
}
};
class C {
double x;
expC prop1; // XX
public:
C() : x(0.0), prop1(x) // XX
{ }
void inc() {
x += 1;
prop1.inc(); // XX
}
void dec() {
x -= 1;
prop1.dec(); // XX
}
void set(double x_) {
x = x_;
prop1.recompute(x); // XX
}
};
XX
标记我需要对类 C
进行的更改。这是很多变化,很容易出错。它变得更加复杂,有几个属性,我什至相互依赖。
class C {
double x;
expC prop1; // XX
someC prop2; // XX
public:
C() : x(0.0), prop1(x), prop2(x, prop1) // XX
{ }
void inc() {
x += 1;
prop1.inc(); // XX
prop2.inc(); // XX
}
void dec() {
x -= 1;
prop1.dec(); // XX
prop2.dec(); // XX
}
void set(double x_) {
x = x_;
prop1.recompute(x); // XX
prop2.recompute(x, prop1); // XX
}
};
问题:这样一个程序的好的设计是什么?我相信有可能比上面做得更好。目标是:1) 使添加/删除此类属性或打开/关闭它们的计算变得容易 2) 性能至关重要。 inc
和 dec
在紧密的内部循环中被调用并且做的事情相对较少。出于性能原因,它们不能虚拟化。
实际上 x
是一个更复杂的数据结构。想想例如在 graph 中添加/删除边缘并在此过程中跟踪其度数序列。
更新
@tobi303 要求我展示如何使用这个类。它的方式类似于:
void simulate(C &c) {
for (/* lots of iterations */) {
c.inc();
double p1 = c.prop1.value();
double p2 = c.prop2.value();
if (condition(p1,p2))
c.dec();
}
}
或者换句话说:
它实际上是一个类似于 Metropolis-Hasting algorithm 的蒙特卡洛模拟.
一个具体的例子可能是 C
类中的“数据”(状态)是 Ising model 的自旋状态。 (对于熟悉它的人)和属性是系统的总能量和总磁化强度。在一次旋转翻转后更新这些比从头开始重新计算要快得多。实际上我没有伊辛模型,我有一些更复杂的东西。我有几个属性,有些计算速度快,有些速度慢(实际上我有一些辅助数据结构可以帮助计算属性)。我需要尝试不同属性的组合,因此我经常更改代码中包含的内容。有时我会实现新的属性。当我不需要一个已经实现的属性时,我需要能够出于性能原因关闭它的计算(有些计算速度非常慢)。
最佳答案
只是be lazy并且不要在需要时计算属性。它将删除大量代码和不必要的计算。
当您确实需要您的属性时,如果它不在缓存中则计算它。因此,您需要为每个属性设置一个 bool 值来判断缓存是否是最新的,并且您需要在每次 x
本身更新时使 bool 值无效。
基本上:
class C {
double x;
template <typename Value> struct cachedProp {
bool cache = false;
Value value;
}
cachedProp<expC> prop1;
cachedProp<someC> prop2;
//...
void invalidateCache() {
prop1.cache = false;
prop2.cache = false;
//...
}
public:
expC getProperty1() {
if (!prop1.cache) {
recalculateProp1();
prop1.cache = true;
}
return prop1.value;
}
void inc() {
x += 1;
invalidateCache();
}
};
编辑:一个更懒的解决方案是不在缓存
中存储一个 bool 值,而是存储一个与上次更新相对应的整数并在C中维护一个计数器
。每次缓存失效时,C
中的计数器都会增加。获取 propX
时,如果计数器与 propX.lastUpdate
不匹配,则更新 `propX。
这样,使缓存失效只是一个操作,不必更新所有属性的缓存。
关于c++ - 如何设计这个易于修改的程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37418954/
前言: 有时候,一个数据库有多个帐号,包括数据库管理员,开发人员,运维支撑人员等,可能有很多帐号都有比较大的权限,例如DDL操作权限(创建,修改,删除存储过程,创建,修改,删除表等),账户多了,管理
这个问题已经有答案了: Condition variable deadlock (2 个回答) 已关闭 5 年前。 在研究多线程时,我编写了以下代码,但在屏幕上没有观察到输出。我在这里做错了什么?我期
复制代码 代码如下: <IfModule mod_rewrite.c> RewriteEngineOn RewriteBase/ #将www.zzvips.com跳转到www.zzv
复制代码 代码如下: <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / # 把 www.zzvips.com
复制代码 代码如下: Const T_GATEWAY = "1.1.1.1" '网关 Const T_NEWDNS1 = "2.2.2.2" 'DNS1
0. 修改索引 大文本字段支持排序 PUT http://localhost:9200/lrc_blog/_mapping //请求体 { "properties": { "title": { "t
仅 react 当状态发生变化时重新渲染 . 那么为什么我会直接看到我对真实 DOM 所做的更改呢? 我知道我正在修改真实的 DOM,但是当我根本没有改变状态时触发重新渲染的是什么。 import R
Xcode beta 5 推出 @FetchRequest对于 SwiftUI。 我有一个 View ,它有一个 @FetchRequest . NSFetchRequest是在管理器中创建的,该管理
关闭。这个问题需要更多 focused .它目前不接受答案。 想改进这个问题?更新问题,使其仅关注一个问题 editing this post . 7年前关闭。 Improve this questi
我有一个表达式[text][id]应替换为链接 text 解决方案是( id 是整数) $s = preg_replace("/\[([^\]]+)(\]*)\]\[([0-9]+)\]/","$1$
我在 repo 中有一个文件,我不想让任何人更新。 我能做什么? 最佳答案 你想要svn锁:http://www.linxit.de/svnbook/en/1.2/svn.ref.svn.c.lock
说我有项目 list 。我想导出到csv,但在此之前我想做一些计算/修改。 基本上,设置如下所示: PS C:\Files> gci Directory: C:\Files Mode
我有一个非常简单的问题 - 是否可以修改 Java API 的源代码,例如Junit,JABX ? 我知道这似乎是一个非常愚蠢的问题,但它一直困扰着我一段时间。 最佳答案 如果您可以掌握源代码,那么请
我有一个带有变量/列的小标题,其中包括不同形状的小标题列表。我想为其中一个变量中的每个(子)标题添加一个变量/列。 例如此类数据 library("tibble") aaa aaa # A tibb
我有几个菜单,可以在单击时向当前链接添加变量。这是一个例子: 1 2 3 x y z 我的问题是,如果我选择“y”2次,它会添加“&cord=y”2次。相反,我希望它替
我有两个项目:一个服务项目和一个服务安装程序项目。服务项目具有适合我的产品的装配信息。它包括公司信息和正确的服务名称。一旦服务实际安装,所有这些似乎都会被忽略。安装服务时,它使用在服务安装程序的ini
以下代码何时可能产生副作用? @some = map { s/xxx/y/; $_ } @some; perlcritic 将其解释为危险的,因为例如: @other = map { s/xxx/y/
我想知道以下哪种解决方案更好:我想修改一些 .class 文件,我意识到有两种方法可以做到这一点: 反编译.class文件,修改它,最后再次编译。 - 直接用十六进制编辑器修改。 谢谢 最佳答案 在这
这是我的按钮代码 onclick 我希望我的程序等待用户单击一个 JPanel,并且当用户单击 JPanel 时,它应该在控制台上打印其名称。 此按钮代码未显示输出 JPopupMenu popu
我正在使用一个具有“getName()”方法的特定 API。 getName() 返回一个字符串。是否可以修改该字符串? API 中不包含修饰符方法,并且 String getName() 返回的是私
我是一名优秀的程序员,十分优秀!