阅读更多

1顶
1踩

编程语言

原创新闻 C++之父:C++ 的五个普遍误解(3)

2014-12-29 10:53 by 正式编辑 cao345657340 评论(0) 有4995人浏览
为了增加您冬天阅读的乐趣,我们很荣幸地奉上Bjarne Stroustrup大神的这个包含3个部分的系列文章。第一部分在这里第二部分在这里

5. 误解4:“为了效率,你必须编写底层代码”

许多人相信高效率的代码必须是底层代码。一些人甚至认为底层代码天生就是高效的(“如果代码很丑陋,那它一定很高效!一定有人花费了大量时间和精力来优化它!”)。当然,你仅仅使用底层代码是可以写出高效代码的,并且有时在直接处理机器资源时必须使用底层代码。然而,你一定要衡量一下你的工作是否有价值:现代C++编译器非常高效,而现代机器架构非常复杂。如果必须使用底层代码,一定要通过接口封装起来,以便于使用。通常,通过高层接口封装底层代码,会带来更好的优化(如,避免“滥用”底层代码)。在关注效率的场合,首先尝试用高层抽象来呈现需要的解决方案,而不要不加考虑地使用比特位和指针。

5.1 C语言的qsort()

考虑一个简单的例子。如果你需要对一组浮点数执行降序排序,你可以写一段代码来实现。然而,除非你有极端特殊的需求(如,有内存容纳不下的大量数据),这样做就太天真了。数十年来,我们一直有性能可接受的排序算法库。我最不喜欢的就是ISO标准C的qsort()算法:
int greater(const void* p, const void* q)  // three-way compare
{
  double x = *(double*)p;  // get the double value stored at the address p
  double y = *(double*)q;
  if (x>y) return 1;
  if (x<y) return -1;
  return 0;
}
 
void do_my_sort(double* p, unsigned int n)
{
  qsort(p,n,sizeof(*p),greater);
}
 
int main()
{
  double a[500000];
  // ... fill a ...
  do_my_sort(a,sizeof(a)/sizeof(*a));  // pass pointer and number of elements
  // ...
}

如果你不是一个C程序员,或者你没有使用过qsort,那么需要解释一下;qsort接收4个参数:

  • 指向顺序存储字节的指针
  • 数据元素个数
  • 每个数据元素的字节数
  • 一个比较函数,参数是指向数据元素首个字节的指针
注意,这个接口丢失了信息。我们真正地目的不是对字节数据排序。我们要对浮点数排序,但是qsort并不知道,因此我们不得不提供如何比较浮点数以及浮点数占用的字节个数等信息。当然,如果编译器知道这些信息就更好了。然而,qsort的低层次接口阻止了编译器使用类型信息。不得不显式地声明简单信息也会增加出现错误的机会。qsort()函数的两个整数参数的顺序写错了吗?如果我写错了,编译器不会注意到。我的compare()函数的返回值是否遵循了C的3路比较的默认约定呢?

如果你阅读了qsort()函数的一个工业强度实现(请阅读一下),你会发现它努力地去弥补缺少的信息。例如,用交换一定数量字节的方式,来取代更有效率的浮点数交换。间接地调用比较函数也很耗时,除非编译器使用常量方式传递指针。

5.2 C++’s sort()

比较一下qsort()的C++等价实现,sort():
void do_my_sort(vector<double>& v)
{
  sort(v,[](double x, double y) { return x>y; });  // sort v in decreasing order
}
 
int main()
{
  vector<double> vd;
  // ... fill vd ...
  do_my_sort(v);
  // ...
}

这里不需要太多解释。vector知道它的长度,因此我们不需要再显式地传递元素个数了。我们不会“丢失”元素类型信息,因此也不需要处理元素的字节数。默认地,sort()以升序排序,因此我需要指定比较条件,就像在qsort()中做的一样。这里,我传递了一个使用>符号比较浮点数的lambda表达式。通常,这个lambda表达式会被我所知道的所有C++编译器内链编译,因此实际上比较操作变成了一个greater-than的机器指令;这里没有(低效的)间接函数调用。

我使用了sort()的容器版本,以避免显式地使用迭代器。即,避免像下面这样写:
std::sort(v.begin(),v.end(),[](double x, double y) { return x>y; });

我也可以更进一步,使用C++14的比较对象:
sort(v,greater<>()); // sort v in decreasing order

哪个版本更快呢?你可以不使用任何性能优化指令,编译C版本的qsort()和C++版本,因此这是一个真正的编程风格的比较,而不是语言的比较。标准库实现似乎一直使用与sort和qsort相同的算法,因此这是一个编程风格的比较,而不是算法的比较。当然,不同的编译器和库实现会给出不同的结果,但是对于每种实现,我们对不同层次抽象的结果有一个合理的认识。

最近我运行了这个例子,并且发现sort()版本比qsort()版本快2.5倍。你会因为编译器和机器的差别,得到不同的结果,但是我从来没看到qsort打败过sort。我甚至看到过sort比qsort快10倍。为什么呢?很明显C++标准库sort相比qsort,是一个更高层次的抽象,更通用和灵活。它类型安全,并使存储类型,元素类型和排序算法参数化。它里面看不到指针,类型转换,长度,或者字节。C++标准库STL,包括sort,努力地尝试不丢失任何信息,从而得到了良好的内链和优化效果。

普适性和高层代码能够击败低层代码。当然不是一直这样,但是sort/qsort的比较不是一个孤立案例。总是从高层,精准和类型安全的版本开始解决方案。(仅当)如果需要时则优化。

6. 误解5:“C++只适用于大型、复杂的程序”

C++是一个巨型的语言。它定义的大小和C#与Java差不多。但是这并不意味着你必须知道每一个细节,或者在每一个程序中都用到所有特性。考虑一个只使用标准库基本组件的例子:
set<string> get_addresses(istream& is)
{
  set<string> addr;
  regex pat { R"((\w+([.-]\w+)*)@(\w+([.-]\w+)*))"}; // email address pattern
  smatch m;
  for (string s; getline(is,s); )                    // read a line
    if (regex_search(s, m, pat))                     // look for the pattern
      addr.insert(m[0]);                             // save address in set
  return addr;
}

我假设你知道正则表达式。如果不知道,现在或许是一个阅读它的好时机。注意,我使用move语法来对返回潜在地大量字符串进行简化和提升效率(译者注:move语法在本系列第二篇讲解)。所有的标准库容器都支持move构造方法,因此这里不需要使用new。

为了能正常工作,我需要引用适当的标准库组件:
#include<string>
#include<set>
#include<iostream>
#include<sstream>
#include<regex>
using namespace std;

测试一下:
istringstream test {  // a stream initialized to a sting containing some addresses
  "asasasa\n"
  "bs@foo.com\n"
  "ms@foo.bar.com$aaa\n"
  "ms@foo.bar.com aaa\n"
  "asdf bs.ms@x\n"
  "<span class="MathJax_Preview">\(bs.ms@x\)</span><script type="math/tex">bs.ms@x</script>goo\n"
  "cft foo-bar.ff@ss-tt.vv@yy asas"
  "qwert\n"
};
 
int main()
{
  auto addr = get_addresses(test);  // get the email addresses
  for (auto& s : addr)              // write out the addresses
    cout << s << '\n';
}

这仅仅是一个例子。可以很容易地修改get_addresses(),把regex模式作为参数,从而它能够找到URL或者其他任何东西。也可以很容易地修改get_addresses(),使在每行文字识别超过一个模式。虽然C++是为灵活性和通用性而设计的,但不是每个程序都是一个完整的库,或者应用程序框架。然而,这里的关键点是,从流数据中提取邮件地址任务能够被简单地实现,并很容易测试。

6.1 库

对任何语言,只使用语言内置特性(如if,for和+)编写程序是相当乏味的。通常,会给出适当的库(如图形,路线规划和数据库),可以让几乎所有的任务都能够在合理的工作量内完成。

ISO C++标准库相对小一些(相对于商业库),但是“就在那里”,有大量的开源和商业库。例如,利用(开源或有版权的)库,如Boost[3],POCO[2],AMP[4],TBB[5],Cinder[6],vxWidgets[7],和CGAL[8],很多通用和专业的任务变得简单。作为例子,让我们修改上面的程序,从网页内读取URL。首先,我们改变get_addresses()来查找符合模式的任意字符串:
set<string> get_strings(istream& is, regex pat)
{
  set<string> res;
  smatch m;
  for (string s; getline(is,s); )  // read a line
  if (regex_search(s, m, pat))
    res.insert(m[0]);              // save match in set
  return res;
}

这很简单。接下来,我们需要考虑如何登录到网页并读取文件。Boost有一个库,asio,可以与网页通讯:
#include “boost/asio.hpp” // get boost.asio

需要连接到web服务器:
int main()
try {
  string server = "www.stroustrup.com";
  boost::asio::ip::tcp::iostream s {server,"http"};  // make a connection
  connect_to_file(s,server,"C++.html");    // check and open file
 
  regex pat {R"((http://)?www([./#\+-]\w*)+)"}; // URL
  for (auto x : get_strings(s,pat))    // look for URLs
    cout << x << '\n';
}
catch (std::exception& e) {
  std::cout << "Exception: " << e.what() << "\n";
  return 1;
}

查看www.stroustrup.com网站上的C++.html文件,内容如下:
http://www-h.eng.cam.ac.uk/help/tpl/languages/C++.html
 
http://www.accu.org
 
 
http://www.artima.co/cppsource
 
 
http://www.boost.org
 
...

我使用了set类型,因此URL会以字母顺序打印出来。

我在一个函数(connect_to_file())中偷偷地“隐藏”了检测和HTTP连接管理,这并非不切实际:
void connect_to_file(iostream& s, const string& server, const string& file)
  // open a connection to server and open an attach file to s
  // skip headers
{
  if (!s)
    throw runtime_error{"can't connect\n"};
 
  // Request to read the file from the server:
  s << "GET " << "http://"+server+"/"+file << " HTTP/1.0\r\n";
  s << "Host: " << server << "\r\n";
  s << "Accept: */*\r\n";
  s << "Connection: close\r\n\r\n";
 
  // Check that the response is OK:
  string http_version;
  unsigned int status_code;
  s >> http_version >> status_code;
 
  string status_message;
  getline(s,status_message);
  if (!s || http_version.substr(0, 5) != "HTTP/")
    throw runtime_error{ "Invalid response\n" };
 
  if (status_code!=200)
    throw runtime_error{ "Response returned with status code" };
 
  // Discard the response headers, which are terminated by a blank line:
  string header;
  while (getline(s,header) && header!="\r")
    ;
}

由于这是最常见的,我没有从头开始。HTTP连接管理大部分是从Christopher Kohlhoff的asio文档[9]中复制来的。

6.2 Hello,World!

C++是一种编译型语言,设计它的首要目标是在关注性能和可靠性的场合,提供良好、可维护的代码(如,基础设施[10])。它不是有意在小型程序中,直接和解释型或小型编译“脚本”语言竞争。的确,这类语言(如JavaScript,或Java)通常是用C++实现的。但是有很多只有数十行或几百行的很有用的C++程序。

这里提供一个能简单尝试的“Hello,World”例子,而不是(只)关注一个库聪明和先进的部分。简单安装一个最小化的库,写一个最多一页的“Hello,World”例子,展示一个库能够做什么。在某些时候我们都是菜鸟。这里,我C++版本的“Hello,World”是:
#include<iostream>
 
int main()
{
  std::cout << "Hello, World\n";
}

在展示ISO C++和标准库的时候,我发现了更长、更复杂、更无趣的版本。

7. 误解的多种“用途”

在现实中误解有时是有基础的。对每一个误解,某些人都会有多次经验或情形导致他们有理由相信。今天,我认为它们是完全错误的、被误解的,实话实说。一个问题是,误解通常是为了支撑一个目的——或者它们已经消失了。这5个误解扮演着多个角色:

  • 提供安慰:不需要改变;不需要尝试变革。这样感到很舒适。变化可能失败,因此相信新事物不可行会更好。
  • 在开始一个新项目时,这样可以节省时间:如果你(你自己)知道C++是什么,你不需要再花费时间学习新知识。你不需要尝试新技术。你不需要衡量潜在的性能障碍。你不需要培训新的开发者。
  • 你可以不必学习C++:如果这些误解是真的,你究竟为什么要学习C++?
  • 促进替换语言和技术:如果这些误解是真的,那么明显需要替换。
但是这些误解不是真的,因此理智地改进现状,替换C++,或者避免现代C++编程风格,都不能依靠这些借口。从旧的C++观点来看(用熟悉的语言子集和技巧)可能会舒服一点,但是软件就是这样,改变是必须的。我们可以比C,“带类的C”,C++98等做的更好。

坚持曾经正确的看法,并不是没有代价。相比现代的代码,它的维护代码更高。老的编译器和工具集相比依赖现代结构化代码的现代工具,更加低效和难以分析。

现代C++(C++11,C++14)以及它支持的编程技术,与“常见的误解”所代表的不同,并且比它要好的多。

如果你深信这些误解之一,不要马上就相信我的话,认为它是错误的。尝试。测试。通过你关心的一些问题,衡量“老方法”和新的替换思路。尝试真正地把握学习新工具和技术的时机,使用新方法写代码的时机,应用现代代码的时机。不要忘记与坚持“老方法”比较可能的维护代价。澄清误解的最佳方法是拿出证据。我在这里只呈现例子和做出讨论。

不,这不是一场“C++很完美”的讨论。C++并不完美;它不是对每个人、每件事都最好的语言。其他语言也不是。接受C++现在的样子,而不是20年前它的样子,也不是某些人声明它是什么样子。为了做出理性的选择,拿出一些真正的信息——只要时间允许——亲自尝试目前的C++如何处理你遇到的问题。

8. 总结

不要在没有证据的情况下,相信C++的这些“常识”或使用它。这篇文章呈现了最频繁表达的5个观点,并逐一澄清,说明它们“仅仅是误解”:

  1. “要理解C++,你必须先学习C”
  2. “C++是一门面向对象的语言”
  3. “为了软件可靠性,你需要垃圾回收”
  4. “为了效率,你必须编写底层代码”
  5. “C++只适用于大型、复杂的程序”

它们是有害的。

9. 反馈

还有疑问?告诉我原因。你遇到过其他什么误解了吗?为什么他们相信误解而不是实际经验?你有哪些证据可能揭露一个误解呢?

10. 参考文献

  1. ISO/IEC 14882:2011 Programming Language C++
  2. POCO libraries: http://pocoproject.org/
  3. Boost libraries: http://www.boost.org/
  4. AMP: C++ Accelerated Massive Parallelism. http://msdn.microsoft.com/en-us/library/hh265137.aspx
  5. TBB: Intel Threading Building Blocks. www.threadingbuildingblocks.org/
  6. Cinder: A library for professional-quality creative coding. http://libcinder.org/
  7. vxWidgets: A Cross-Platform GUI Library. www.wxwidgets.org
  8. Cgal – Computational Geometry Algorithms Library. www.cgal.org
  9. Christopher Kohlhoff : Boost.Asio documentation. http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio.html
  10. B. Stroustrup: Software Development for Infrastructure. Computer, vol. 45, no. 1, pp. 47-58, Jan. 2012, doi:10.1109/MC.2011.353.
  11. Bjarne Stroustrup: The C++ Programming Language (4th Edition). Addison-Wesley. ISBN 978-0321563842. May 2013.
  12. Bjarne Stroustrup: A Tour of C++. Addison Wesley. ISBN 978-0321958310. September 2013.
  13. B. Stroustrup: Programming: Principles and Practice using C++ (2nd edition). Addison-Wesley. ISBN 978-0321992789. May 2014.
来自: 伯乐在线
1
1
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • C++之父:C++ 的五个普遍误解(1)

    [编注:为了增加您冬天阅读的乐趣,我们很...本系列包括 3 篇文章,我将向大家展示并澄清关于C++的五个普遍的误解: “要理解C++,你必须先学习C” “C++是一门面向对象的语言” “为了软件可靠性,你需要垃圾回收”

  • C++之父:C++ 的五个普遍误解

    C++之父:C++ 的五个普遍误解 总结一下提到的五点: 1. “要理解C++,你必须先学习C” 2. “C++是一门面向对象的语言” 3. “为了软件可靠性,你需要垃圾回收” 4. “为了效率,你必须编写底层代码” ...

  • C++ 之父 Bjarne Stroustrup : 简单的表述方式才是最优的方案

    作为 C++ 之父,Bjarne Stroustrup 也一直致力于 C++ 标准的改进和推广,其著作《C++编程语言》《C++的设计和演化》和《C++加注参考手册》等已成为C++学习的经典读物。 访谈内容: 除了作为编程技术大师为人熟知...

  • C++之父Bjarne Stroustrup: 简单的表述方式才是最优的方案(图灵访谈)

    作为C++之父,Bjarne Stroustrup也一直致力于C++标准的改进和推广,其著作《C++编程语言》《C++的设计和演化》和《C++加注参考手册》等已成为C++学习的经典读物。 访谈内容: 英文版 除了作为编程技术...

  • Linux之父炮轰C++:糟糕程序员的垃圾语言

    )而且,即使是C程序员所引以为豪的性能优势,现在也岌岌可危了(参见C++之父Stroustrup的 文章 中相关的比较)。 C++目前的困境,很大程度上是由于此前的图书和文献曾经一度倾向于炫技,陶醉于对语言各种细节的深入...

  • C++之模板编程

    C++模板编程总结

  • [英文版]C++之父Bjarne Stroustrup: 简单的表述方式才是最优的方案

    ...作为C++之父,Bjarne Stroustrup也一直致力于C++标准的改进和推广,其著作《C++编程语言》《C++的设计和演化》和《C++加注参考手册》等已成为C++学习的经典读物。 Transcripts: 中文版链接: ...

  • C++复习1:一些概念

    C++内存分为5个区域 (堆栈全常代 ):C/C++ 内存模型。 浅拷贝和深拷贝 浅拷贝只是拷贝一个指针,并没有新开辟一个地址,拷贝的指针和原来的指针指向同一块地址,如果原来的指针所指向的资源释放了,那么再释放浅...

  • 一网打尽:C++远程调试工具和策略全指南

    就像C++之父Bjarne Stroustrup所说:“我们的主要设计目标是,让不可能的事变得可能,让困难的事变得简单。” 1.2 远程调试的挑战和必要性 (Challenges and Necessity of Remote Debugging) 远程调试(Remote ...

  • 【C++运算符重载】运算符重载的艺术与实践:何时使用以及使用示例

    在现代软件开发的世界里,C++语言以其高效性和灵活性而著称。特别是在高性能计算和系统编程领域,C++显示出了它的独特优势。本章将重点讨论C++中的一项高级特性——运算符重载(Operator Overloading),探讨它在...

  • 西门子S7-200PLC与MCGS触摸屏联动控制步进伺服电机的技术解析及应用实例

    内容概要:本文详细介绍了利用西门子S7-200PLC与昆仑通泰MCGS触摸屏联合控制步进伺服电机的方法和技术要点。首先阐述了硬件接线的具体方式,包括PLC输出接口与伺服驱动器之间的正确连接以及必要的安全措施如急停开关的接入。接着深入探讨了PLC程序的核心代码片段,涵盖原点回归、手动正转触发、绝对位置计算等功能模块,并解释了关键指令如PLS的作用及其使用注意事项。此外,针对触摸屏的关键配置进行了说明,涉及数值输入框、指示灯、多状态按钮等组件的设置,强调了绝对定位逻辑的实现。文中还分享了一些常见的调试问题及解决方案,例如伺服电机抖动、数据刷新延迟等问题的处理办法。最后提到该方案已在实际生产环境中成功应用并表现出良好的性能指标。 适合人群:从事自动化控制领域的工程师和技术人员,特别是那些希望深入了解PLC与触摸屏协同工作的专业人士。 使用场景及目标:适用于需要高精度定位控制的小型自动化生产线或机械设备中,旨在帮助用户掌握如何构建稳定可靠的步进伺服控制系统,提高工作效率的同时降低成本。 其他说明:作者凭借丰富的实践经验提供了许多宝贵的建议和技巧,对于初学者而言是非常有价值的参考资料。

  • 光储并网直流微电网Simulink仿真模型:MPPT与混合储能系统的优化设计

    内容概要:本文详细介绍了光储并网直流微电网的Simulink仿真模型构建,涵盖多个关键技术点。首先讨论了光伏系统的最大功率点跟踪(MPPT)算法,特别是扰动观察法的具体实现及其优缺点。接着探讨了由蓄电池和超级电容组成的混合储能系统,强调了它们各自的特点以及如何通过控制算法进行有效的功率分配。此外,还讲解了二阶低通滤波法的应用,用于提高电能质量和优化不同频率范围内的功率管理。最后,文章深入解析了逆变器的双闭环控制系统,包括电压环和电流环的设计,以确保逆变器输出与大电网的良好匹配。 适合人群:从事新能源系统设计、电力电子技术研究的专业人士,尤其是对Simulink仿真工具有所了解的研发人员。 使用场景及目标:适用于希望深入了解光储并网直流微电网内部机制和技术细节的研究者和工程师。主要目标是帮助读者掌握如何利用Simulink工具箱搭建完整的光储并网直流微电网仿真平台,从而为实际工程应用提供理论支持和技术指导。 其他说明:文中提供了大量具体的Matlab/Simulink代码片段,便于读者理解和实践。同时,作者分享了许多宝贵的实战经验和调试技巧,有助于解决实际建模过程中可能遇到的问题。

  • 西门子1200 PLC轴运动控制程序模板:多轴伺服、电缸控制及PLC通信实战应用

    内容概要:本文详细介绍了一套成熟的西门子1200 PLC轴运动控制程序模板,涵盖多轴伺服控制、电缸控制、PLC通信、气缸报警、电路图、威纶通触摸屏程序和IO表等方面的内容。该模板已在多个项目中成功应用,特别是在海康威视的路由器外壳装配机项目中表现优异。文中不仅提供了具体的代码示例,还分享了许多实战经验和技巧,如轴控制块的参数设置、PUT/GET通讯的心跳检测、气缸报警的互锁逻辑、电路图中的电源保护措施等。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是那些需要进行PLC编程和轴运动控制的从业者。 使用场景及目标:①快速掌握西门子1200 PLC轴运动控制的编程方法;②提高PLC程序的稳定性和可靠性;③优化设备性能,确保高效生产和故障预防。 其他说明:该模板不仅适用于新项目的开发,也可以作为现有系统的改进参考。通过学习和应用这些技术和经验,可以显著提升工作效率和产品质量。

  • 智能驾驶领域基于神经网络的驾驶员风格自适应ACC系统安全距离模型研究

    内容概要:本文探讨了基于神经网络训练的不同驾驶员风格自适应ACC(自适应巡航控制)系统,尤其是其安全距离模型的研究。传统ACC系统采用固定的参数设置,难以适应不同驾驶员的驾驶习惯。文中介绍了通过神经网络训练,使ACC系统能够学习并适应不同驾驶员的驾驶风格,从而动态调整安全距离的方法。具体实现了基于LSTM和物理模型融合的混合式神经网络结构,以及定制化的损失函数,确保系统在不同驾驶风格下的安全性和舒适度。实验结果显示,该系统能够在不同驾驶风格间灵活切换,提升应对复杂路况的能力。 适合人群:对智能驾驶技术和机器学习感兴趣的科研人员、工程师和技术爱好者。 使用场景及目标:适用于智能汽车的研发和改进,旨在提高ACC系统的智能化水平,使其更加符合不同驾驶员的习惯,提升驾驶体验和安全性。 其他说明:文章还讨论了模型的实际应用挑战,如不同地区的驾驶文化差异,并提出了相应的解决方案。

  • 计算机三级网络机试考试试题及答案(下).pdf

    计算机三级网络机试考试试题及答案(下).pdf

  • UWB DW1000高精度3D定位系统:基于CH32F103C8T6与卡尔曼滤波的实现及应用

    内容概要:本文详细介绍了基于Decawave UWB DW1000定位模块和CH32F103C8T6控制器构建的高精度3D定位系统。系统分为定位模块和测距模块,前者负责接收并计算用户位置,后者提供测距数据。定位模块采用最小二乘法和扩展卡尔曼滤波相结合的方式,实现了静态和动态环境下的高精度定位。文中还提供了详细的硬件配置、SPI接口初始化、测距算法以及定位算法的代码示例,并通过实验验证了系统的性能。 适合人群:对超宽带(UWB)定位技术和嵌入式开发感兴趣的工程师和技术爱好者。 使用场景及目标:适用于需要高精度室内外定位的应用场景,如AGV调度、人员定位等。目标是帮助开发者理解和实现基于UWB的高精度定位系统。 其他说明:文中提到的关键技术点包括SPI接口配置、双边双向测距算法(DS-TWR)、天线延迟校准、最小二乘法和扩展卡尔曼滤波。此外,作者还分享了一些实用的经验和技巧,如SPI分频系数选择、光速值的精确度、状态方程的设计等。

  • 计算机实训总结.pdf

    计算机实训总结.pdf

  • 单片机课程设计-温度监控系统的设计

    单片机课程设计__温度监控系统的设计

  • 基于深度强化学习的微能源网能量管理与优化策略研究——使用DQN实现智能调度算法

    内容概要:本文详细探讨了利用深度强化学习(特别是DQN算法)进行微能源网的能量管理和优化调度。文中介绍了微能源网面临的挑战,如风光出力的不确定性以及传统优化算法的局限性。作者通过具体案例展示了如何构建微电网环境类MicrogridEnv,定义状态空间、动作空间和奖励函数,并实现了DQN神经网络架构。此外,还讨论了经验回放、双网络结构等关键技术细节,以及如何通过特征工程提高模型性能。最终,通过实际测试验证了DQN算法的有效性和优势。 适合人群:从事微能源网、智能电网研究的技术人员,对深度强化学习感兴趣的开发者,以及希望了解如何将机器学习应用于能源领域的研究人员。 使用场景及目标:适用于需要优化微能源网能量管理的场景,旨在提高能源利用率、降低成本并确保供电稳定性。主要目标是通过智能算法应对风光出力的不确定性和用户需求的波动,从而实现高效的能源调度。 其他说明:文章不仅提供了理论分析和技术实现,还包括了许多实用的经验分享和调试技巧,有助于读者更好地理解和应用深度强化学习于实际项目中。

Global site tag (gtag.js) - Google Analytics