由于小编刚刚接触MOOS-Ivp及C++、linux等,对于MOOS-Ivp前置知识只能边学边记录:
本练习中要解决的一个主要问题是如何构建一个应用程序,测试输入将由另一个应用程序产生。一个应用程序发送一个素数,另一个应用程序分解为不同质数的乘积以后将求解的内容返回。
一、下载自己的可扩展MOOS-Ivp树,moos-ivp-extend。
二、进入moos-ivp-extend/src,使用指令构建一个新的应用程序。
$ GenMOOSApp PrimeFactor p "John Doe"
三、将其添加到CMakeList.txt中
四、注意:
扩展全新的pPrimeFactor应用程序以读取邮件NUM_VALUE,并确定它是偶数还是奇数,然后相应地发布新邮件。测试是通过UPOKEDDB完成的。
使用UTimeScript通过脚本中的一组值代替UPOKEDB测试上面的值。
处理迭代()循环内的偶数/奇数判定。在NewMail()中构建一个传入列表的C++列表,并在Idter()中处理此列表。
五、pPrimeFor应用程序的说明
应用程序主要应该满足以下要求:
①、你的应用程序应该被称为pPrimeFactor。
②、你的应用程序应该注册并处理变量NUM_VALUE值,应用程序应该接受这个包含64位整数值的变量的邮件。最大值为,或1844 67407370955 1615,为64位无符号整数的最大值。你可以假设只有正整数作为输入。
③、传入变量是字符串类型。必须将其转换为代码中的数值。
④、应用程序应该确定给定输入的主要因素列表,并为每个输入生成以下输出:
原始数字,
指示接收到的顺序的索引,
指示其计算顺序的索引,
解决分解的时间。这是在正常的时钟时间,而不是CPU时间。使用MOSIMTIME()函数获取接收到的时间和完成的时间。
主要因素的列表。
一个唯一的ID指定你,例如,你的用户名。
⑤、输出变量应该是PRIME_RESULT结果,格式如下。请注意,如果一个数可以由一个素数均匀地除以一次,如下面的两个3的例子,列出结果中的每一个:
PRIME_RESULT = "orig=90090,received=34,calculated=33,solve_time=2.03, primes=2:3:3:5:7:11:13,username=jane"
⑥、应用程序不应该被大量数字所阻塞。无论前面查询的大小如何,我们都应该能够立即看到对低数量查询的响应。
⑦、不要使用已知素数的缓存。
六、关键点介绍:
本练习的关键问题是设计pPrimeFactor应用程序来处理任何大小的数字,但不能阻塞于处理的数字。某些小的数字,以及一小列素数的数字,使它们能够非常快速地计算它们的素因子集。其他数字,如任何20位质数,在确定其结果之前需要更多的步骤。你的应用程序应该能够很快接收到包含数字的邮件。
其目的是设计你的应用程序来快速处理和发布容易数字的结果,并且当接收到较难的数字时,不要延迟容易数字的结果。您需要建立一个工作队列(以C++列表的形式)来保存新到的和未解决的数字。您需要在OnNewMail()函数中填充该队列。你需要在你的迭代()方法中对这个队列“工作”。
关键思想是每次调用Iterate()时,都会对队列中的每个项应用固定数量的素因式分解计算。对于某些元素,这将足以完成计算。它们可以从队列中删除,并以传出邮件的形式将其答案发送到MOOSDB。对于当前回合中不能完成的元素,它们将保留在队列中,以便在下一次调用Iterate()时进行连接。诀窍是为任何未完成的工作保存“状态”。
最后,我们将使用我们的uTimerScript数字序列来检查一个正常工作的pPrimeFactor应用程序,其中混合了简单数字和硬数字。我们将检查这些因素的正确计算,并检查硬数没有阻止容易的数字。
七、C++相关内容
①无符号长整数:
pPrimeFactor应用程序需要接受和处理非负整数,对于64位整数,最大值为:
unsigned long int value = 184467440739429084;
传统上,这是通过使用以下C++数据类型实现的。但是,在一些旧的C++编译器中,“unsigned long int”数据类型只有32位。在最新的编译器中,它们是64位。可以肯定的是,下面的数据类型变得更加常见,而在较新的编译器中,老式的将产生警告。我们将使用这个实验室中最新的样式:
#include <cstdint> uint64_t value = 184467440739429084;
②为什么MOOS的输入要设置成字符串模式
MOOS消息要么是字符串类型,要么是双精度类型。字符串类型实际上允许表示任何其他复杂数据类型,因此基本上可能的消息类型是无限的。双类型是方便表示小数的,但在这里用不到。
C++中的双类型是8字节,或64位。类型uint64_t也为64位。他们都能够代表或1844 67407370955 1615不同的数字。不同之处在于,对于int64_t变量,仅表示范围[0,18446744073709551615]中的整数。对于双精度,所有负数、所有浮点非整数值(例如,23.87432)和高于18446744073709551615的数字都被填充到相同的64位中。这不可避免地意味着一些数字是不可表示的,而是映射到附近的“闭合”数。这是一些大整数值从数字大于15位数开始的情况。
这意味着,如果我们想要通过MOOS消息精确地传递大量数字,那么我们应该使用数字的字符串表示。因此,在我们的情况下,如果我们想要构成一个大的18-20位质数,我们需要使用字符串。
③字符串到数字,数字到字符串转换
在这个实验室里,你需要在字符串和数值之间执行一些转换。若要表示一个64位整数,我们希望使用uint64_t类型。
#include <cstdint> uint64_t value = 0;
在这个实验室中,如果使用实验室中提供的uTimerScript脚本,这些数字将作为字符串值发布到变量NUM_VALUE。例如:
NUM_VALUE="5674032334252535"。
若要将字符串从STR=“5674032334252535”转换为一个“int64_t”,可以使用:
#include <cstdlib> // for the strtoul() function string str = "5674032334252535" uint64_t value = strtoul(str.c_str(), NULL, 0);
在另一个方面,将数值转换为字符串,可以使用C++ stringstream类来实现:
#include <sstream> .... // Create the biggest unsigned long int possibe uint64_t ival = 18446744073709551615; // Convert it to a string stringstream ss; ss << ival; string str = ss.str(); // Confirm it works cout << "Value:" << str << endl;
④用于字符串分析的极好的工具
在这个实验室中,需要生成以逗号分隔变量=值对的字符串形式发布的结果,如下所示。
PRIME_RESULT = "orig=90090,received=34,calculated=33,solve_time=2.03”
八、对于该实验的建议
构建复杂代码的有效策略是识别相对容易的不同阶段,其中每个阶段都是(a)可验证的,(b)更接近于整体解决方案,(c)不需要在每个阶段之间进行大量重新工作。考虑到这一点,在实验中提供了以下不同的阶段:
①构建并编译
②增加你的应用程序接受和处理数值输入
未完待续。。。。。