gtest使用初级指南
之前在 http://blog.csdn.net/fengbingchun/article/details/39667571 中对google的开源库gtest进行过介绍,现在看那篇博文,感觉有些没有说清楚,这里再进行总结下:
Google Test是Google的开源C++单元测试框架,简称gtest。它的License是New BSD License,可以商用。它是跨平台的,不仅可以应用在各PC端(Windows、Linux、Mac),也可以应用在各移动端(Android、iOS)。目前最新的稳定版为1.8.0,可从 https://github.com/google/googletest/releases 下载源码。
在Windows下编译gtest source code比较简单,因为源码中在googletest/msvc目录下已经有gtest.sln工程,直接双击打开即可。
单元测试(Unit Test)是对软件基本组成单元(如函数或是一个类的方法)进行的测试,是开发者编写的一小段代码,用于检验被测试代码一个很小的、很明确的功能是否正确。
在gtest中,一个测试用例(test case)可以包含一个或多个测试。一个测试程序可以包含多个测试用例。
一、断言(Assertions)
gtest中,断言是用以检查条件是否为真,用以验证测试code的行为。一个断言的结果包括成功(success)、非致命失败(nonfatal failure)、致命失败(fatal failure)三种。断言是宏,类似于函数调用。
断言可以分为两类,一类是ASSERT_*系列,一类是EXPECT_*系列,它们的区别:EXPECT_*版本的断言失败时产生非致命失败,但不会中止当前函数。ASSERT_*版本的断言失败时会产生致命失败,并结束当前函数,当前函数中ASSERT_*后面的语句将不会执行。
ASSERT_*常常被用于后续测试逻辑强制依赖的处理结果的断言,如创建对象后检查指针是否为空,若为空,则后续对象方法调用会失败;而EXPECT_*则用于即使失败也不会影响后续测试逻辑的处理结果的断言,如某个方法返回结果的多个属性的检查。
ASSERT_*(expected,actual)/EXPECT_EQ(expected, actual),应该把想要测试的表达式放在actual的位置,把期望值放在expected的位置。
可以通过操作符”<<”将一些自定义的信息输出,如:
EXPECT_EQ(v1, v2) << “this is a error!”;
断言包括:
(1)、true/false:ASSERT_TRUE(condition)、ASSERT_FALSE(condition)
(2)、compare two values:ASSERT_EQ(val1, val2)、ASSERT_NE(val1, val2)、ASSERT_LT(val1, val2)、ASSERT_LE(val1, val2)、ASSERT_GT(val1, val2)、ASSERT_GE(val1, val2)
(3)、string comparison: ASSERT_STREQ(str1, str2)、ASSERT_STRNE(str1,str2)、ASSERT_STRCASEEQ(str1, str2)、ASSERT_STRCASENE(str1,str2)
其中带”CASE”的断言是忽略大小写比较。从后缀名就应该可以区分每个比较的意义,如TRUE(条件为真)、FALSE(条件为假)、EQ(=)、NE(!=)、LT(<)、LE(<=)、GT(>)、GE(>=)。以上均存在对应的EXPECT_*断言。
二、TEST()宏
为了创建一个test:
(1)、使用TEST()来定义和命名一个test函数。TEST()宏是普通的C++函数,没有返回值。
(2)、在test函数内部,可以包含任何有效地C++语句,并由gtest断言来检查值。
(3)、此test函数结果由断言决定,有任何断言错误(fatally or non-fatally)或在此函数内部产生crash,则此test失败,否则成功。
TEST()包含两个参数,从一般到具体。第一个参数表示这个测试用例(test case)的名字,第二个参数表示在这个test case中这个test的名字。名字必须是有效地C++标识符,不能包含下划线。一个test的全名由test case和其自身名称组成。
gtest用test case来管理所有test,所以逻辑上相关的test应该放到同一个test case中。
三、TEST_F()宏
如果你写的多个test都在操作类似的数据,那么你能使用test fixture。它允许你在多个不同的test中复用相同的对象配置。
为了创建一个fixture:
(1)、派生一个类继承自::testing::Test,并使用protected或public限定符,因为后面将会从子类中访问fixture的成员。
(2)、在这个派生类里,声明你想使用的所有对象。
(3)、如果必要,编写一个默认构造函数或SetUp()函数来准备每个测试对象。
(4)、如果必要,写一个析构函数或TearDown()函数释放你在SetUp()中分配的任何资源。
(5)、如果需要,为你的tests定义共享函数。
当用fixture时,用TEST_F()代替TEST(),因为在test fixture中,TEST_F()允许你访问对象和共享函数。
像TEST(),TEST_F()也有两个参数,第一个是test case的名字,但是这个名字必须是test fixture类的名字。
在使用TEST_F()之前,你必须先定义一个test fixture类。
对于用TEST_F()定义的每一个test,gtest将会:
(1)、在运行时,创建一个全新的test fixture对象。
(2)、通过SetUp()函数立即初始化它。
(3)、运行test.
(4)、调用TearDown()函数清理申请的资源。
(5)、删除test fixture对象。在相同的test case中,不同的test有不同的test fixture对象,在创建下一个test fixture对象前,gtest总会先删除test fixture。在多个test中,gtest不能重用相同的test fixture。在一个test中对test fixture所作的改变不会影响其它的test。
四、testing::InitGoogleTest(argc,argv)函数
testing::InitGoogleTest函数对gtest框架进行初始化,并解析命令行参数,移除所有识别的标志。它允许用户通过各种标志控制测试程序的行为,如可设置重复运行测试次数、将结果输出到xml文件。必须在调用RUN_ALL_TESTS之前调用它,它还负责注册需要运行的所有测试用例。
五、RUN_ALL_TESTS()宏
在定义了所有的test后,通过RUN_ALL_TESTS()执行它们。
RUN_ALL_TESTS():负责执行所有测试,运行所有test,在代码中只能调用一次,如果所有tests成功,返回0,否则返回1。它会自动地探测并运行你链接到的所有测试----它们可以来自不同的测试用例,甚至是来自不同的文件。在默认情况下,结果输出到标准输出。
当调用RUN_ALL_TESTS()宏时:
(1)、保存所有gtest标志的状态。
(2)、为第一个test创建一个test fixture对象。
(3)、通过SetUp()函数初始化。
(4)、在这个fixture对象上运行这个test。
(5)、通过fixture的TearDown()函数释放资源。
(6)、删除这个fixture对象。
(7)、恢复所有gtest标志的状态。
(8)、为下一个test重复上面的操作步骤,直至运行完所有tests。
只能调用RUN_ALL_TESTS()一次。
更详细介绍可参考官网:https://github.com/google/googletest/blob/master/googletest/docs/Primer.md
以下的test code主要来自gtest中的samples:
funset.hpp:
#ifndef FBC_GTEST_TEST_FUNSET_HPP_
#define FBC_GTEST_TEST_FUNSET_HPP_#include <string>// reference: googletest/samples/
// Returns n! (the factorial of n). For negative n, n! is defined to be 1.
int Factorial(int n);
// Returns true iff n is a prime number.
bool IsPrime(int n);///
// A simple string class.
class MyString {
private:const char* c_string_;const MyString& operator=(const MyString& rhs);public:// Clones a 0-terminated C string, allocating memory using new.static const char* CloneCString(const char* a_c_string);// The default c'tor constructs a NULL string.MyString() : c_string_(NULL) {}// Constructs a MyString by cloning a 0-terminated C string.explicit MyString(const char* a_c_string) : c_string_(NULL) {Set(a_c_string);}// Copy c'torMyString(const MyString& string) : c_string_(NULL) {Set(string.c_string_);}// D'tor. MyString is intended to be a final class, so the d'tor// doesn't need to be virtual.~MyString() { delete[] c_string_; }// Gets the 0-terminated C string this MyString object represents.const char* c_string() const { return c_string_; }size_t Length() const {return c_string_ == NULL ? 0 : strlen(c_string_);}// Sets the 0-terminated C string this MyString object represents.void Set(const char* c_string);
};//
// Queue is a simple queue implemented as a singled-linked list.
// The element type must support copy constructor.
template <typename E> // E is the element type
class Queue;// QueueNode is a node in a Queue, which consists of an element of
// type E and a pointer to the next node.
template <typename E> // E is the element type
class QueueNode {friend class Queue<E>;public:// Gets the element in this node.const E& element() const { return element_; }// Gets the next node in the queue.QueueNode* next() { return next_; }const QueueNode* next() const { return next_; }private:// Creates a node with a given element value. The next pointer is set to NULL.explicit QueueNode(const E& an_element) : element_(an_element), next_(NULL) {}// We disable the default assignment operator and copy c'tor.const QueueNode& operator = (const QueueNode&);QueueNode(const QueueNode&);E element_;QueueNode* next_;
};template <typename E> // E is the element type.
class Queue {
public:// Creates an empty queue.Queue() : head_(NULL), last_(NULL), size_(0) {}// D'tor. Clears the queue.~Queue() { Clear(); }// Clears the queue.void Clear() {if (size_ > 0) {// 1. Deletes every node.QueueNode<E>* node = head_;QueueNode<E>* next = node->next();for (;;) {delete node;node = next;if (node == NULL) break;next = node->next();}// 2. Resets the member variables.head_ = last_ = NULL;size_ = 0;}}// Gets the number of elements.size_t Size() const { return size_; }// Gets the first element of the queue, or NULL if the queue is empty.QueueNode<E>* Head() { return head_; }const QueueNode<E>* Head() const { return head_; }// Gets the last element of the queue, or NULL if the queue is empty.QueueNode<E>* Last() { return last_; }const QueueNode<E>* Last() const { return last_; }// Adds an element to the end of the queue. A copy of the element is// created using the copy constructor, and then stored in the queue.// Changes made to the element in the queue doesn't affect the source// object, and vice versa.void Enqueue(const E& element) {QueueNode<E>* new_node = new QueueNode<E>(element);if (size_ == 0) {head_ = last_ = new_node;size_ = 1;}else {last_->next_ = new_node;last_ = new_node;size_++;}}// Removes the head of the queue and returns it. Returns NULL if// the queue is empty.E* Dequeue() {if (size_ == 0) {return NULL;}const QueueNode<E>* const old_head = head_;head_ = head_->next_;size_--;if (size_ == 0) {last_ = NULL;}E* element = new E(old_head->element());delete old_head;return element;}// Applies a function/functor on each element of the queue, and// returns the result in a new queue. The original queue is not// affected.template <typename F>Queue* Map(F function) const {Queue* new_queue = new Queue();for (const QueueNode<E>* node = head_; node != NULL; node = node->next_) {new_queue->Enqueue(function(node->element()));}return new_queue;}private:QueueNode<E>* head_; // The first node of the queue.QueueNode<E>* last_; // The last node of the queue.size_t size_; // The number of elements in the queue.// We disallow copying a queue.Queue(const Queue&);const Queue& operator = (const Queue&);
};#endif // FBC_GTEST_TEST_FUNSET_HPP_
funset.cpp:#include "funset.hpp"// reference: googletest/samples///
// Returns n! (the factorial of n). For negative n, n! is defined to be 1.
int Factorial(int n) {int result = 1;for (int i = 1; i <= n; i++) {result *= i;}return result;
}// Returns true iff n is a prime number.
bool IsPrime(int n) {// Trivial case 1: small numbersif (n <= 1) return false;// Trivial case 2: even numbersif (n % 2 == 0) return n == 2;// Now, we have that n is odd and n >= 3.// Try to divide n by every odd number i, starting from 3for (int i = 3;; i += 2) {// We only have to try i up to the squre root of nif (i > n / i) break;// Now, we have i <= n/i < n.// If n is divisible by i, n is not prime.if (n % i == 0) return false;}// n has no integer factor in the range (1, n), and thus is prime.return true;
}///
// Clones a 0-terminated C string, allocating memory using new.
const char* MyString::CloneCString(const char* a_c_string) {if (a_c_string == NULL) return NULL;const size_t len = strlen(a_c_string);char* const clone = new char[len + 1];memcpy(clone, a_c_string, len + 1);return clone;
}// Sets the 0-terminated C string this MyString object
// represents.
void MyString::Set(const char* a_c_string) {// Makes sure this works when c_string == c_string_const char* const temp = MyString::CloneCString(a_c_string);delete[] c_string_;c_string_ = temp;
}
test_TEST.cpp:#include <iostream>
#include <vector>
#include <string>
#include <gtest/gtest.h>
#include "funset.hpp"// reference: googletest/samples/
// Tests factorial of negative numbers.
TEST(FactorialTest, Negative) {// This test is named "Negative", and belongs to the "FactorialTest"// test case.EXPECT_EQ(1, Factorial(-5));EXPECT_EQ(1, Factorial(-1));EXPECT_GT(Factorial(-10), 0);
}// Tests factorial of 0.
TEST(FactorialTest, Zero) {EXPECT_EQ(1, Factorial(0));
}// Tests factorial of positive numbers.
TEST(FactorialTest, Positive) {EXPECT_EQ(1, Factorial(1));EXPECT_EQ(2, Factorial(2));EXPECT_EQ(6, Factorial(3));EXPECT_EQ(40320, Factorial(8));
}// Tests negative input.
TEST(IsPrimeTest, Negative) {// This test belongs to the IsPrimeTest test case.EXPECT_FALSE(IsPrime(-1));EXPECT_FALSE(IsPrime(-2));EXPECT_FALSE(IsPrime(INT_MIN));
}// Tests some trivial cases.
TEST(IsPrimeTest, Trivial) {EXPECT_FALSE(IsPrime(0));EXPECT_FALSE(IsPrime(1));EXPECT_TRUE(IsPrime(2));EXPECT_TRUE(IsPrime(3));
}// Tests positive input.
TEST(IsPrimeTest, Positive) {EXPECT_FALSE(IsPrime(4));EXPECT_TRUE(IsPrime(5));EXPECT_FALSE(IsPrime(6));EXPECT_TRUE(IsPrime(23));
}/
// Tests the default c'tor.
TEST(MyString, DefaultConstructor) {const MyString s;EXPECT_STREQ(NULL, s.c_string());EXPECT_EQ(0u, s.Length()) << "ok";
}const char kHelloString[] = "Hello, world!";// Tests the c'tor that accepts a C string.
TEST(MyString, ConstructorFromCString) {const MyString s(kHelloString);EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));EXPECT_EQ(sizeof(kHelloString) / sizeof(kHelloString[0]) - 1, s.Length());fprintf(stderr, "Print Info: sizeof(kHelloString): %d, sizeof(kHelloString[0]): %d, s.Length(): %d\n",sizeof(kHelloString), sizeof(kHelloString[0]), s.Length());
}// Tests the copy c'tor.
TEST(MyString, CopyConstructor) {const MyString s1(kHelloString);const MyString s2 = s1;EXPECT_EQ(0, strcmp(s2.c_string(), kHelloString));
}// Tests the Set method.
TEST(MyString, Set) {MyString s;s.Set(kHelloString);EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));// Set should work when the input pointer is the same as the one// already in the MyString object.s.Set(s.c_string());ASSERT_EQ(0, strcmp(s.c_string(), kHelloString));// Can we set the MyString to NULL?s.Set(NULL);EXPECT_STREQ(NULL, s.c_string());
}
test_TEST_F.cpp:#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include <gtest/gtest.h>
#include "funset.hpp"// reference: googletest/samples/
// To use a test fixture, derive a class from testing::Test.
class QueueTest : public testing::Test {
protected: // You should make the members protected s.t. they can be// accessed from sub-classes.// virtual void SetUp() will be called before each test is run. You// should define it if you need to initialize the varaibles.// Otherwise, this can be skipped.virtual void SetUp() override {q1_.Enqueue(1);q2_.Enqueue(2);q2_.Enqueue(3);}// virtual void TearDown() will be called after each test is run.// You should define it if there is cleanup work to do. Otherwise,// you don't have to provide it.//// virtual void TearDown() {// }// A helper function that some test uses.static int Double(int n) {return 2 * n;}// A helper function for testing Queue::Map().void MapTester(const Queue<int> * q) {// Creates a new queue, where each element is twice as big as the// corresponding one in q.const Queue<int> * const new_q = q->Map(Double);// Verifies that the new queue has the same size as q.ASSERT_EQ(q->Size(), new_q->Size());// Verifies the relationship between the elements of the two queues.for (const QueueNode<int> * n1 = q->Head(), *n2 = new_q->Head();n1 != NULL; n1 = n1->next(), n2 = n2->next()) {EXPECT_EQ(2 * n1->element(), n2->element());}delete new_q;}// Declares the variables your tests want to use.Queue<int> q0_;Queue<int> q1_;Queue<int> q2_;
};// When you have a test fixture, you define a test using TEST_F instead of TEST.// Tests the default c'tor.
TEST_F(QueueTest, DefaultConstructor) {// You can access data in the test fixture here.EXPECT_EQ(0u, q0_.Size());
}// Tests Dequeue().
TEST_F(QueueTest, Dequeue) {int * n = q0_.Dequeue();EXPECT_TRUE(n == NULL);n = q1_.Dequeue();ASSERT_TRUE(n != NULL);EXPECT_EQ(1, *n);EXPECT_EQ(0u, q1_.Size());delete n;n = q2_.Dequeue();ASSERT_TRUE(n != NULL);EXPECT_EQ(2, *n);EXPECT_EQ(1u, q2_.Size());delete n;
}// Tests the Queue::Map() function.
TEST_F(QueueTest, Map) {MapTester(&q0_);MapTester(&q1_);MapTester(&q2_);
}/
// teaches how to reuse a test fixture in multiple test cases by deriving sub-fixtures from it
class QuickTest : public testing::Test {
protected:// Remember that SetUp() is run immediately before a test starts.// This is a good place to record the start time.virtual void SetUp() override {start_time_ = time(NULL);}// TearDown() is invoked immediately after a test finishes. Here we// check if the test was too slow.virtual void TearDown() override {// Gets the time when the test finishesconst time_t end_time = time(NULL);// Asserts that the test took no more than ~5 seconds. Did you// know that you can use assertions in SetUp() and TearDown() as// well?EXPECT_TRUE(end_time - start_time_ <= 5) << "The test took too long.";}// The UTC time (in seconds) when the test startstime_t start_time_;
};// We derive a fixture named IntegerFunctionTest from the QuickTest
// fixture. All tests using this fixture will be automatically
// required to be quick.
class IntegerFunctionTest : public QuickTest {// We don't need any more logic than already in the QuickTest fixture.// Therefore the body is empty.
};// Now we can write tests in the IntegerFunctionTest test case.
// Tests Factorial()
TEST_F(IntegerFunctionTest, Factorial) {// Tests factorial of negative numbers.EXPECT_EQ(1, Factorial(-5));EXPECT_EQ(1, Factorial(-1));EXPECT_GT(Factorial(-10), 0);// Tests factorial of 0.EXPECT_EQ(1, Factorial(0));// Tests factorial of positive numbers.EXPECT_EQ(1, Factorial(1));EXPECT_EQ(2, Factorial(2));EXPECT_EQ(6, Factorial(3));EXPECT_EQ(40320, Factorial(8));
}// Tests IsPrime()
TEST_F(IntegerFunctionTest, IsPrime) {// Tests negative input.EXPECT_FALSE(IsPrime(-1));EXPECT_FALSE(IsPrime(-2));EXPECT_FALSE(IsPrime(INT_MIN));// Tests some trivial cases.EXPECT_FALSE(IsPrime(0));EXPECT_FALSE(IsPrime(1));EXPECT_TRUE(IsPrime(2));EXPECT_TRUE(IsPrime(3));// Tests positive input.EXPECT_FALSE(IsPrime(4));EXPECT_TRUE(IsPrime(5));EXPECT_FALSE(IsPrime(6));EXPECT_TRUE(IsPrime(23));
}//
// teaches how to reuse a test fixture in multiple test cases by deriving sub-fixtures from it
class QueueTest_2 : public QuickTest {
protected:virtual void SetUp() override {// First, we need to set up the super fixture (QuickTest).QuickTest::SetUp();// Second, some additional setup for this fixture.q1_.Enqueue(1);q2_.Enqueue(2);q2_.Enqueue(3);}// By default, TearDown() inherits the behavior of// QuickTest::TearDown(). As we have no additional cleaning work// for QueueTest, we omit it here.//// virtual void TearDown() override {// QuickTest::TearDown();// }Queue<int> q0_;Queue<int> q1_;Queue<int> q2_;
};// Tests the default constructor.
TEST_F(QueueTest_2, DefaultConstructor) {EXPECT_EQ(0u, q0_.Size());
}// Tests Dequeue().
TEST_F(QueueTest_2, Dequeue) {int* n = q0_.Dequeue();EXPECT_TRUE(n == NULL);n = q1_.Dequeue();EXPECT_TRUE(n != NULL);EXPECT_EQ(1, *n);EXPECT_EQ(0u, q1_.Size());delete n;n = q2_.Dequeue();EXPECT_TRUE(n != NULL);EXPECT_EQ(2, *n);EXPECT_EQ(1u, q2_.Size());delete n;
}
test_TEST.cpp(main function):#include <iostream>
#include <vector>
#include <gtest/gtest.h>int main()
{std::vector<char*> argv{
#ifdef _DEBUG"E:/GitCode/Messy_Test/lib/dbg/x64_vc12/gtest_Test.exe",
#else"E:/GitCode/Messy_Test/lib/rel/x64_vc12/gtest_Test.exe",
#endif//"--gtest_repeat=2 ", // 重复运行测试次数//"--gtest_break_on_failure", // 遇到failure退出"--gtest_filter=*", // 指定需要运行的tests//"--gtest_print_time=0", // don't print the elapsed time of each test"--gtest_output=xml:E:/GitCode/Messy_Test/testdata/info.xml" // 结果输出到指定的xml文件};int argc = argv.size();// Initializes Google Test. This must be called before calling RUN_ALL_TESTS()testing::InitGoogleTest(&argc, argv.data());// Use this function in main() to run all tests. It returns 0 if all// tests are successful, or 1 otherwiseint ret = RUN_ALL_TESTS();if (ret == 0) fprintf(stderr, "========== all tests are succeseful =========\n");else fprintf(stderr, "********** some tests are failed **********\n");return ret;
}
执行结果如下:相关文章:

iOS视频流采集概述(AVCaptureSession)
需求:需要采集到视频帧数据从而可以进行一系列处理(如: 裁剪,旋转,美颜,特效....). 所以,必须采集到视频帧数据. 阅读前提: 使用AVFoundation框架采集音视频帧数据GitHub地址(附代码) : iOS视频流采集概述 简书地址 : iOS视频流采…

300秒搞定第一超算1万年的计算量,量子霸权时代已来?
(由AI科技大本营付费下载自视觉中国)作者 | 马超责编 | 郭芮来源 | CSDN 博客近日,美国航天局(NASA)发布了一篇名为《Quantum Supremacy Using a Programmable Superconducting Processor》的报道,称谷歌的…

2014-3-6 星期四 [第一天执行分析]
昨日进度: [毛思想]:看测控技术量待定 --> [良]超额完成,昨天基本上把测控看了一大半啦 [汇编]:认真听课,边听边消化自学 --> [中]基本满足,还需要抽时间总结,特别是前面寻址的各种情况…
行列式介绍及Eigen/OpenCV/C++的三种实现
行列式,记作det(A),是一个将方阵A映射到实数的函数。行列式等于矩阵特征值的乘积。行列式的绝对值可以用来衡量矩阵参与矩阵乘法后空间扩大或者缩小了多少。如果行列式是0,那么空间至少沿着某一维完全收缩了,使其失去了所有的体积…

基于Go的语义解析开源库FMR,“屠榜”模型外的NLP利器
(由AI科技大本营付费下载自视觉中国)作者 | 刘占亮 一览群智技术副总裁编辑 | Jane出品 | AI科技大本营(ID:rgznai100)如何合理地表示语言的内在意义?这是自然语言处理业界中长久以来悬而未决的一个命题。在…

【高级数据类型2】- 10. 接口
2019独角兽企业重金招聘Python工程师标准>>> Go语言-接口 在Go语言中,一个接口类型总是代表着某一种类型(即所有实现它的类型)的行为。一个接口类型的声明通常会包含关键字type、类型名称、关键字interface以及由花括号包裹的若干…

Linux软件包命令
2019独角兽企业重金招聘Python工程师标准>>> dpkg命令: dpkg -i **/**.deb 安装软件 dpkg -x **.deb 解开.deb文件 dpkg -r /-p 删除并清配置 更详细的 用dpkg --help 查询 如下: dpkg -i|--install <.deb 文件的文件名> ... | -R|--re…
Caffe中计算图像均值的实现(cifar10)
在深度学习中,在进行test时经常会减去train数据集的图像均值,这样做的好处是:属于数据预处理中的数据归一化,降低数据间相似性,可以将数值调整到一个合理的范围。以下code是用于计算cifar10中训练集的图像均值…

阿里云弹性公网IP(EIP)的使用限制
阿里云弹性公网IP(EIP)是一种可以独立购买和持有的公网IP地址资源,弹性公网IP具有独立购买持有、弹性绑定和配置灵活等优势,但实际使用中弹性公网IP也是有很多限制的,阿里云惠网分享弹性公网IP(EIP…

400名微软员工主动曝光薪资:28万元到228万元不等!
作者 | Dave Gershgorn译者 | 弯月,编辑 | 郭芮来源 | CSDN(ID:CSDNnews)【导读】近日,近400名微软员工分享了他们的薪酬(从4万美元到32万美元不等,约为28万人民币到228万人民币)&am…

Extjs:添加查看全部按钮
var grid new Ext.grid.GridPanel({renderTo:tsllb,title:产品成本列表,selModel:csm,height:350,columns:[csm,{header: "编码", dataIndex: "bm", sortable: true,hidden:true},{header: "产品", dataIndex: "cp", sortable: true},…

练手扎实基本功必备:非结构文本特征提取方法
作者 | Dipanjan (DJ) Sarkar编译 | ronghuaiyang来源 | AI公园(ID:AI_Paradise)【导读】本文介绍了一些传统但是被验证是非常有用的,现在都还在用的策略,用来对非结构化的文本数据提取特征。介绍在本文中,我们将研究如…
范数介绍及C++/OpenCV/Eigen的三种实现
有时我们需要衡量一个向量的大小。在机器学习中,我们经常使用被称为范数(norm)的函数衡量向量大小。形式上,Lp范数定义如下:范数(包括Lp范数)是将向量映射到非负值的函数。直观上来说,向量x的范数衡量从原点到点x的距离。更严格地…

js添加网页水印和three.js场景中加水印
我们在日常网页开发的时候,可能想给自己的网页或者canvas里面添加水印,增添个人标记,我这里分为普通静态html页面和threejs中3d场景里面添加水印功能。一 静态html页面添加水印你只需要在你的页面添加一个图片遮罩,通过绝对定位和…

JAVA学习笔记(6)
关于多线程的优先级,这个程序里面,现在计算机比较好,int存储不下了,我跑了好几次都是负分,特把int改成long。但是之后跑出来的结果,两个数字都差不多,不知道是什么问题?等待答案中。…

C++/C++11中std::deque的使用
std::deque是双端队列,可以高效的在头尾两端插入和删除元素,在std::deque两端插入和删除并不会使其它元素的指针或引用失效。在接口上和std::vector相似。与sdk::vector相反,std::deque中的元素并非连续存储:典型的实现是使用一个…

贾扬清:我对人工智能方向的一点浅见
阿里妹导读:作为 AI 大神,贾扬清让人印象深刻的可能是他写的AI框架Caffe ,那已经是六年前的事了。经过多年的沉淀,成为“阿里新人”的他,对人工智能又有何看法?最近,贾扬清在阿里内部分享了他的…

吴甘沙:天外飞“厕”、红绿灯消失,未来无人驾驶将被重新定义
整理 | 夕颜出品 | AI科技大本营(ID:rgznai100)2019 年9 月 5 日至 7 日,由新一代人工智能产业技术创新战略联盟(AITISA)指导,鹏城实验室、北京智源人工智能研究院支持,专业中文 IT 技术社区 CS…

Linux内核--网络栈实现分析(二)--数据包的传递过程--转
转载地址http://blog.csdn.net/yming0221/article/details/7492423 作者:闫明 本文分析基于Linux Kernel 1.2.13 注:标题中的”(上)“,”(下)“表示分析过程基于数据包的传递方向:”…

C++/C++11中std::stack的使用
栈stack 是一个容器适配器(container adaptor)类型,被特别设计用来运行于LIFO(Last-in First-out,后进先出)场景,在该场景中,只能从容器末尾添加和删除元素,其定义在stack头文件中。stack默认基于std::deque实现&#…

团队前四次作业——个人总结
团队前四次作业——个人总结 描述 团队名称待就业六人组相关团队第四次作业答辩——反思与总结做了哪些事?工作量、完成度 作业负责工作量完成度团队队员展示创意合照后期1h95%项目选题报告编写创新和收益部分2h85%项目原型设计原型设计6h95%需求规格说明书功能需求…

吴甘沙:天外飞“厕”、红绿灯消失,未来无人驾驶将被重新定义 | AI ProCon 2019
2019 年9 月 5 日至 7 日,由新一代人工智能产业技术创新战略联盟(AITISA)指导,鹏城实验室、北京智源人工智能研究院支持,专业中文 IT 技术社区 CSDN 主办的 2019 中国 AI 开发者大会(AI ProCon 2019&#x…

MySQL基础day03_数据的导入、导出-MySQL 5.6
MySQL基础day03_数据的导入、导出-MySQL 5.6注:把数据按照一定格式存放到文件里才能进行数据的导入。1,数据导入的条件把文件里的内容保存到数据的表里;把数据按照一定格式存放文件里;注:默认情况下,只有管…
“含光”剑出,谁与争锋?阿里重磅发布首颗AI芯片含光800
作者 | 夕颜、胡巍巍 编辑 | 唐小引 出品 | AI 科技大本营(ID:rgznai100) 9 月末的杭州气温适宜,宜出游,宜在湖边餐厅浅酌一杯清茶消闲。但在钱塘江水支流河畔的云栖小镇,却完全一副与闲适氛围不相称的热闹景象。 …

c++面试题中经常被面试官面试的小问题总结(一)(本篇偏向基础知识)
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/10711810.html 1.类中的函数定义后加了一个const代表什么? 代表它将具备以下三个性质:1.const对象只能调用const成员函数。2.const对象的值不能被修改,在…
矩阵特征分解介绍及雅克比(Jacobi)方法实现特征值和特征向量的求解(C++/OpenCV/Eigen)
对角矩阵(diagonal matrix):只在主对角线上含有非零元素,其它位置都是零,对角线上的元素可以为0或其它值。形式上,矩阵D是对角矩阵,当且仅当对于所有的i≠j, Di,j 0. 单位矩阵就是对角矩阵,对角元素全部是1…
Entity Framework CodeFirst数据迁移
原文:Entity Framework CodeFirst数据迁移前言 紧接着前面一篇博文Entity Framework CodeFirst尝试。 我们知道无论是“Database First”还是“Model First”当模型发生改变了都可以通过Visual Studio设计视图进行更新,那么对于Code First如何更新已有的模型呢&…
限时早鸟票 | 2019 中国大数据技术大会(BDTC)超豪华盛宴抢先看!
2019 年12月5-7 日,由中国计算机学会主办,CCF 大数据专家委员会承办,CSDN、中科天玑数据科技股份有限公司协办的 2019 中国大数据技术大会,将于北京长城饭店隆重举行。届时,超过百位技术专家及行业领袖将齐聚于此&…

Google AI 系统 DeepMind无法通过 高中数学
Google 旗下 DeepMind 团队让 AI 系统接受一项高中程度的数学测试,结果在 40 道题目中只答对了 14 题,甚至连「1111111」也算错了。说来难以置信,Google AI 系统能打败人类世界棋王,却无法通过高中程度的数学考试。上周࿰…

C++11中std::tuple的使用
std::tuple是类似pair的模板。每个pair的成员类型都不相同,但每个pair都恰好有两个成员。不同std::tuple类型的成员类型也不相同,但一个std::tuple可以有任意数量的成员。每个确定的std::tuple类型的成员数目是固定的,但一个std::tuple类型的…