NDArray源码解析及测试代码

1)NDArray头文件:

#ifndef NDArray_H
#define NDArray_H#include <set>#include <epicsMutex.h>
#include <epicsTime.h>
#include <ellLib.h>#include "NDAttribute.h"
#include "NDAttributeList.h"
#include "Codec.h"/** NDArray中维度的最大数目 */
#define ND_ARRAY_MAX_DIMS 10/**  NDArray属性"colorMode"的颜色模式枚举 */
typedef enum
{NDColorModeMono,    /**< 单色 */NDColorModeBayer,   /**< Bayer模式图,  每个像素1个值,但在探测器上带有颜色过滤 */NDColorModeRGB1,    /**< 像素颜色交错的RGB图像, 数据数组是[3, NX, NY] */NDColorModeRGB2,    /**< 行颜色交错的RGB图像 ,   数据数组是[NX, 3, NY]  */NDColorModeRGB3,    /**< 面颜色交错的RGB图像 , 数据数组是[NX, NY, 3]  */NDColorModeYUV444,  /**< YUV 图像, 3字节编码1个RGB像素 */NDColorModeYUV422,  /**< YUV 图像, 4字节编码2个RGB像素 */NDColorModeYUV411   /**< YUV 图像, 6字节编码4个RGB像素 */
} NDColorMode_t;/** NDArray属性"bayerPattern"的Bayer颜色枚举. 这个值仅对colorMode是NDColorModeBayer才有意义,* 因为在读出一个芯片子集时,Bayer模式将变化,所以需要这个值,例如如果X或Y偏移值不是偶数。*/
typedef enum
{NDBayerRGGB        = 0,    /**< 第一行RGRG, 第二行GBGB... */NDBayerGBRG        = 1,    /**< 第一行GBGB, 第二行RGRG... */NDBayerGRBG        = 2,    /**< 第一行GRGR, 第二行BGBG... */NDBayerBGGR        = 3     /**< 第一行BGBG, 第二行GRGR... */
} NDBayerPattern_t;/**  定义一个NDArray维度的结构体 */
typedef struct NDDimension {size_t size;    /**< 数组的这个维度中元素数目 */size_t offset;  /**< 相对于原始的数据来源(例如,探测器)的原点的偏移量。* 如果探测器的一个选取区域被读取,则这个值可以大于0.* 在unbinned像素中和默认方向,非反向中指定这个偏移值,* 偏移值是累积的,因此如果一个诸如NDPluginROI的插件进一步选取了一个子区域,* 这个偏移量是相对于探测器中第一个元素,而不是相对于传递给NDPluginROI的区域的第一个元素。*/int binning;    /**< binning(像素求和,1=no binning)相对于原始的数据来源(例如,探测器)* 偏移值是累积的,因而如果一个诸如NDPluginROI的插件执行binning,* 相对于探测器中像素而不是相对于传递给NDPluginROI的可能的binned像素表达这个binning。*/int reverse;    /**< 相对于原先的数据来源(例如,探测器)的方向(0=normal,1=reversed)* 这个值是累积的,因此如果一个诸如NDPluginROI的插件反向这些数据,值必须反映相对于原先探测器的方向,* 而不是相对于传递给NDPluginROI的可能的反向数据。*/
} NDDimension_t;/**  由NDArray::getInfo返回的结构体 */
typedef struct NDArrayInfo {size_t nElements;       /**< 数组中元素的总数 */int bytesPerElement;    /**< 数组中每个元素的字节数*/size_t totalBytes;      /**< 保存这个数组所需的字节总数;这可以小于NDArray::dataSize  *//**< 以下对彩色图(RGB1,RGB2,RGB3)最有用 */NDColorMode_t colorMode; /**< 颜色模式 */int xDim;               /**< 数组索引,它是X维度 */int yDim;               /**< 数组索引,它是Y维度 */int colorDim;           /**< 数组索引,它是颜色维度 */size_t xSize;           /**< 这个数组的X尺寸 */size_t ySize;           /**< 这个数组的Y尺寸 */size_t colorSize;       /**< 这个数组的颜色尺寸 */size_t xStride;         /**< X值之间数组元素的数目 */size_t yStride;         /**< Y值之间数组元素的数目*/size_t colorStride;     /**< 颜色值间数组元素的数目 */
} NDArrayInfo_t;/** * N维度数组类;每个数组有一个维度,数据类型,数据指针以及可选的属性的集合。* 一个数组也有一个标识自身的uniqueId和timeStamp。NDArray对象可以由一个NDArrayPool对象分配,* 出于内存管理,NDArrayPool对象维护一个NDArrays的空闲列表。* */
class ADCORE_API NDArray {
public:/* 方向 */NDArray();NDArray(int ndims, size_t *dims, NDDataType_t dataType, size_t dataSize, void *pData);virtual ~NDArray();int          initDimension   (NDDimension_t *pDimension, size_t size);static int   computeArrayInfo(int ndims, size_t *dims, NDDataType_t dataType, NDArrayInfo *pInfo);int          getInfo         (NDArrayInfo_t *pInfo);int          reserve();int          release();int          getReferenceCount() const {return referenceCount;}int          report(FILE *fp, int details);friend class NDArrayPool;private:ELLNODE      node;              /**< 这必须首先出现,因为ELLNODE必须与NDArray对象有相同地址 */int          referenceCount;    /**< 这个NDArray的引用计数,等于正在使用它的客户端数目  */public:class NDArrayPool *pNDArrayPool;  /**<  创建这个数组的NDArrayPool对象 */class asynNDArrayDriver *pDriver; /**<  创建这个数组的asynNDArrayDriver*/int           uniqueId;     /**<        在一个驱动启动后,由它产生的所有NDArrays中一个必须唯一的编号。*/double        timeStamp;    /**<        这个数组以秒为单位的时间戳;推荐从EPICS纪元(00:00:00 UTC, January 1, 1990)的秒数但某些驱动可以使用一个不同的起始的时间。*/epicsTimeStamp epicsTS;     /**<         epicsTimeStamp,用pasynManager->updateTimeStamp()设置这个变量,并且可以来自一个用户定义的时间戳源。 */int           ndims;        /**<        这个数组中维度数目,最小=1 */NDDimension_t dims[ND_ARRAY_MAX_DIMS];   /**< 这个数组的维度尺寸的数组;前ndims个值是有意义 */NDDataType_t  dataType;                  /**< 这个数组的数据类型 */size_t        dataSize;                  /**< 这个数组的数据尺寸;为*pData分配的实际内存量,可以多于保存这个数组所需的内存量 */void          *pData;                    /**< 指向数组数据的指针,认为按dims[0]变化最快,dims[ndims-1]变化最慢的顺序存储这些数据。 */NDAttributeList *pAttributeList;         /**< 属性的链表 */Codec_t codec;                           /**< 用于压缩这些数据的codec定义. */size_t compressedSize;                   /**< 压缩数据的尺寸。如果pData未被压缩,应该与dataSize相等。*/
};/*这个类定义了一个被包含在std::multilist中的对象,std::multilist用于排序这个freeList_中的NDArrays它定义了一个<操作符,用于使用NDArray::dataSize作为排序键。我们想要在NDArrayPool.cpp中隐藏这个类,并且只是在这里先引用了它。//class sortedListElement;*/
class freeListElement {public:freeListElement(NDArray *pArray, size_t dataSize) {pArray_ = pArray;dataSize_ = dataSize;}friend bool operator<(const freeListElement& lhs, const freeListElement& rhs) {return (lhs.dataSize_ < rhs.dataSize_);}NDArray *pArray_;size_t dataSize_;private:freeListElement(); // 默认构造器是私有的,因而对象不能被无参构建
};/** * NDArrayPool对象维护一个NDArrays的空闲列表(池)。驱动程序从这个池分配NDArray对象,并且传递这些对象给插件。* 当插件放置这个NDArray对象到它们的队列时,它们增加对这个对象的索引,而在它们处理完这个数组后,* 减少对这个对象的索引。当索引计数再次到达0时,这个NDArray对象被放回到空闲列表。* 这种机制使得在插件中数组的复制最小化。*/
class ADCORE_API NDArrayPool {
public:NDArrayPool  (class asynNDArrayDriver *pDriver, size_t maxMemory);virtual ~NDArrayPool() {}NDArray*     alloc(int ndims, size_t *dims, NDDataType_t dataType, size_t dataSize, void *pData);NDArray*     copy(NDArray *pIn, NDArray *pOut, bool copyData, bool copyDimensions=true, bool copyDataType=true);int          reserve(NDArray *pArray);int          release(NDArray *pArray);int          convert(NDArray *pIn,NDArray **ppOut,NDDataType_t dataTypeOut,NDDimension_t *outDims);int          convert(NDArray *pIn,NDArray **ppOut,NDDataType_t dataTypeOut);int          report(FILE  *fp, int details);int          getNumBuffers();size_t       getMaxMemory();size_t       getMemorySize();int          getNumFree();void         emptyFreeList();protected:/** * 应该由管理派生自NDArray类的对象的池类,实现以下方法。*/virtual NDArray* createArray();virtual void onAllocateArray(NDArray *pArray);virtual void onReserveArray(NDArray *pArray);virtual void onReleaseArray(NDArray *pArray);private:std::multiset<freeListElement> freeList_;epicsMutexId listLock_;      /**< 保护这个空闲列表 */int          numBuffers_;size_t       maxMemory_;     /**< 允许这个对象分配的最大内存字节量; -1=无限*/size_t       memorySize_;    /**< 这个对象当前已经分配的内存字节量 */class asynNDArrayDriver *pDriver_; /**< 创建这个对象的asynNDArrayDriver */
};#endif

2)NDArray的实现源文件:

#include <string.h>
#include <stdio.h>
#include <ellLib.h>
#include <vector>#include <epicsTypes.h>
#include <cantProceed.h>#include "NDArray.h"/** NDArray constructor, no parameters. NDArray构造器,不带参数。* 初始化所有字段为0,创建属性链表和链表互斥锁。*/
NDArray::NDArray() // referenceCount,pNDArrayPool,pDriver, uniqueId,timeStamp,ndims, dataType(NDInt8),pData: referenceCount(0), pNDArrayPool(0), pDriver(0),uniqueId(0), timeStamp(0.0), ndims(0), dataType(NDInt8),dataSize(0),  pData(0)
{this->epicsTS.secPastEpoch = 0;this->epicsTS.nsec = 0;memset(this->dims, 0, sizeof(this->dims)); // dims这个数组中元素全部填0memset(&this->node, 0, sizeof(this->node)); // ELLNODE node成员结构体填0 this->pAttributeList = new NDAttributeList(); // 一个空的属性链表
}NDArray::NDArray(int nDims, size_t *dims, NDDataType_t dataType, size_t dataSize, void *pData): referenceCount(0), pNDArrayPool(0), pDriver(0),uniqueId(0), timeStamp(0.0), ndims(nDims), dataType(dataType), // 设置维度数目,每个维度上元素数目,数据类型,数据尺寸未传入值dataSize(dataSize),  pData(0)
{static const char *functionName = "NDArray::NDArray";this->epicsTS.secPastEpoch = 0;this->epicsTS.nsec = 0;this->pAttributeList = new NDAttributeList();this->referenceCount = 1;memset(this->dims, 0, sizeof(this->dims));for (int i=0; i<ndims && i<ND_ARRAY_MAX_DIMS; i++) {this->dims[i].size = dims[i]; // 每一个维度上元素数目this->dims[i].offset = 0;this->dims[i].binning = 1;this->dims[i].reverse = 0;}NDArrayInfo arrayInfo;this->getInfo(&arrayInfo); // 获取数组信息//如果传入dataSize为0,则根据维度数目,每一维度上的元素数目,以及元素类型计算数据尺寸if (dataSize == 0) dataSize = arrayInfo.totalBytes; // if (arrayInfo.totalBytes > dataSize) {printf("%s: ERROR: required size=%d passed size=%d is too small\n",functionName, (int)arrayInfo.totalBytes, (int)dataSize);}/* 如果调用这传递了一个有效的缓存,使用这个缓存,相信它的尺寸是正确的 */if (pData) {this->pData = pData;} else {// 如果传递了一个NULL,则分配这个内存空间this->pData = malloc(dataSize);this->dataSize = dataSize;}
}/** NDArray析构器* 释放这个数据数组,删除所有属性,释放属性列表并且销毁互斥量 */
NDArray::~NDArray()
{if (this->pData) free(this->pData);delete this->pAttributeList;
}/* * 便捷方法计算数组中总字节数typedef struct NDArrayInfo {size_t nElements;      //总元素数目  int bytesPerElement;   //每个元素所用字节size_t totalBytes;     //总字节数目NDColorMode_t colorMode;int xDim;               int yDim;               int colorDim;           size_t xSize;           size_t ySize;           size_t colorSize;      size_t xStride;        size_t yStride;         size_t colorStride;     } NDArrayInfo_t;// 根据元素数据类型,维度数目和每一个维度上元素数目// 获取每个元素字节数,元素总数以及总字节数信息,存入NDArrayInfo结构体*/
int NDArray::computeArrayInfo(int ndims, size_t *dims, NDDataType_t dataType, NDArrayInfo *pInfo)
{switch(dataType)  // 根据指定的元素数据类型,计算每个元素需要的字节数case NDInt8:pInfo->bytesPerElement = sizeof(epicsInt8);break;case NDUInt8:pInfo->bytesPerElement = sizeof(epicsUInt8);break;case NDInt16:pInfo->bytesPerElement = sizeof(epicsInt16);break;case NDUInt16:pInfo->bytesPerElement = sizeof(epicsUInt16);break;case NDInt32:pInfo->bytesPerElement = sizeof(epicsInt32);break;case NDUInt32:pInfo->bytesPerElement = sizeof(epicsUInt32);break;case NDInt64:pInfo->bytesPerElement = sizeof(epicsInt64);break;case NDUInt64:pInfo->bytesPerElement = sizeof(epicsUInt64);break;case NDFloat32:pInfo->bytesPerElement = sizeof(epicsFloat32);break;case NDFloat64:pInfo->bytesPerElement = sizeof(epicsFloat64);break;default:return(ND_ERROR);break;}pInfo->nElements = 1;for (int i=0; i<ndims; i++) pInfo->nElements *= dims[i]; // 根据维度数目,每个维度上元素数目,计算总元素数目pInfo->totalBytes = pInfo->nElements * pInfo->bytesPerElement; // 根据每个元素所用字节数和总元素数目计算总字节数目return ND_SUCCESS;
}
/** 便捷方法:返回有关NDArray的信息;包括这个数组中元素数目,每个元素的字节数目,以及字节总数。[out] pInfo : 指向一个NDArrayInfo_t结构体的指针,必须已经由调用者分配 . */
int NDArray::getInfo(NDArrayInfo_t *pInfo)
{int i;NDAttribute *pAttribute;size_t *dims_t = new size_t[this->ndims]; // 根据维度数目分配一个数组for (i=0; i<this->ndims; i++) dims_t[i] = this->dims[i].size;  // 数组中每个元素获取这个NDArray对象中每个维度的尺寸// 获取每个元素字节数,元素总数以及总字节数信息,存入NDArrayInfo结构体int status = NDArray::computeArrayInfo(this->ndims, dims_t, this->dataType, pInfo);delete[] dims_t;if (status != ND_SUCCESS) return status;pInfo->colorMode = NDColorModeMono; // 设置颜色模式为单色pAttribute = this->pAttributeList->find("ColorMode"); // 属性列表中能够找到颜色模式,则设置为获取到的颜色模式if (pAttribute) pAttribute->getValue(NDAttrInt32, &pInfo->colorMode);pInfo->xDim        = 0;pInfo->yDim        = 0;pInfo->colorDim    = 0;pInfo->xSize       = 0;pInfo->ySize       = 0;pInfo->colorSize   = 0;pInfo->xStride     = 0;pInfo->yStride     = 0;pInfo->colorStride = 0;if (this->ndims > 0) { pInfo->xStride = 1;// X方向是变化最快的维度pInfo->xSize   = this->dims[0].size;}if (this->ndims > 1) {pInfo->yDim  = 1; // Y方向是变化其次的维度pInfo->yStride = pInfo->xSize;pInfo->ySize   = this->dims[1].size;}if (this->ndims == 3) {switch (pInfo->colorMode) {case NDColorModeRGB1:pInfo->xDim    = 1;pInfo->yDim    = 2;pInfo->colorDim  = 0;pInfo->xStride   = this->dims[0].size;pInfo->yStride   = this->dims[0].size * this->dims[1].size;pInfo->colorStride = 1;break;case NDColorModeRGB2:pInfo->xDim    = 0;pInfo->yDim    = 2;pInfo->colorDim  = 1;pInfo->xStride   = 1;pInfo->yStride   = this->dims[0].size * this->dims[1].size;pInfo->colorStride = this->dims[0].size;break;case NDColorModeRGB3:pInfo->xDim    = 0;pInfo->yDim    = 1;pInfo->colorDim  = 2;pInfo->xStride   = 1;pInfo->yStride   = this->dims[0].size;pInfo->colorStride = this->dims[0].size * this->dims[1].size;break;default:// This is a 3-D array, but is not RGBpInfo->xDim    = 0;pInfo->yDim    = 1;pInfo->colorDim  = 2;pInfo->xStride   = 1;pInfo->yStride   = this->dims[0].size;pInfo->colorStride = this->dims[0].size * this->dims[1].size;break;}pInfo->xSize     = this->dims[pInfo->xDim].size; //xDim为0pInfo->ySize     = this->dims[pInfo->yDim].size; //yDim为1pInfo->colorSize = this->dims[pInfo->colorDim].size;}return(ND_SUCCESS);
}/*初始化维度结构体NDDimension_t为size=size,binning=1,reverse=0,offset=0。[in] pDimension : 指向一个NDDimension_t结构体的指针,必须已经由调用者分配.
*/
int NDArray::initDimension(NDDimension_t *pDimension, size_t size)
{pDimension->size=size;pDimension->binning = 1;pDimension->offset = 0;pDimension->reverse = 0;return ND_SUCCESS;
}/** 调用这个NDArray对象的NDArrayPool::reserve() ; 为这个数组增加引用计数 . */
int NDArray::reserve()
{const char *functionName = "NDArray::reserve";if (!pNDArrayPool) {printf("%s: WARNING, no owner\n", functionName);return(ND_ERROR);}return(pNDArrayPool->reserve(this));
}/** 调用这个NDArray对象的NDArrayPool::reverse(); 减小这个数组的引用计数 . */
int NDArray::release()
{const char *functionName = "NDArray::release";if (!pNDArrayPool) {printf("%s: WARNING, no owner\n", functionName);return(ND_ERROR);}return(pNDArrayPool->release(this));
}/** Reports on the properties of the array. 报告这个数组的性质。* [in] fp : 用于报告输出的文件指针.* [in] details: 所需报告详细程度;如果  >5,调用NDAttributeList::report().*/
int NDArray::report(FILE *fp, int details)
{int dim;fprintf(fp, "\n");fprintf(fp, "NDArray  Array address=%p:\n", this); // NDArray对象的地址fprintf(fp, "  ndims=%d dims=[", this->ndims);     // NDArray对象的维度数目for (dim=0; dim<this->ndims; dim++) fprintf(fp, "%d ", (int)this->dims[dim].size);  // NDArray对象每个维度的元素数目fprintf(fp, "]\n");fprintf(fp, "  dataType=%d, dataSize=%d, pData=%p\n",  // 数据类型,数据尺寸,数据地址this->dataType, (int)this->dataSize, this->pData); fprintf(fp, "  uniqueId=%d, timeStamp=%f, epicsTS.secPastEpoch=%d, epicsTS.nsec=%d\n", // 唯一id,时间戳this->uniqueId, this->timeStamp, this->epicsTS.secPastEpoch, this->epicsTS.nsec);fprintf(fp, "  referenceCount=%d\n", this->referenceCount); // 引用计数fprintf(fp, "  number of attributes=%d\n", this->pAttributeList->count()); // 属性数目if (details > 5) {this->pAttributeList->report(fp, details); // 每个属性信息}return ND_SUCCESS;
}

3)测试代码:

#include <string.h>
#include <stdio.h>
#include <ellLib.h>
#include <vector>
#include <stdlib.h>#include <epicsTypes.h>
#include <epicsEvent.h>
#include <cantProceed.h>
#include <epicsTime.h>
#include <asynDriver.h>#include "NDArray.h"static asynUser * pasynUser = NULL;int main()
{int nDims = 2;size_t dims[2];size_t dataSize = 0;epicsTimeStamp currentTime;//double timeStamp;dims[0] = 3; dims[1] = 5;epicsInt32 * pArrs = NULL;if (!pasynUser){pasynUser = pasynManager->createAsynUser(0,0);}//NDArray * pNDArray = new NDArray(int ndims, size_t *dims, NDDataType_t dataType, size_t dataSize, void *pData);NDArray * pNDArray = new NDArray(nDims, dims, NDInt32,  dataSize, (void *)pArrs) ;// 获取数组数据的存储地址pArrs = (epicsInt32 *)pNDArray->pData;size_t i;size_t total = dims[0] * dims[1];// 对NDArray对象的数组赋值for (i = 0; i < total; i++){pArrs[i] = i;}// 更新timestamp时间戳pasynManager->updateTimeStamp(pasynUser);pNDArray->epicsTS = pasynUser->timestamp;// 更新以秒计的时间戳epicsTimeGetCurrent(&currentTime);pNDArray->timeStamp = currentTime.secPastEpoch + currentTime.nsec / 1.e9;// 调用NDArray对象的report方法 输出这个NDArray对象的信息pNDArray->report(stdout, 10);// 输出NDArray数组中的信息:size_t j;printf("array data Information:\n");for (i = 0; i < dims[1]; i++ ){for (j = 0; j < dims[0]; j++){printf("%u\t", pArrs[i * dims[0] + j]);}printf("\n");}NDArrayInfo_t info;pNDArray->getInfo(&info);printf("\n");printf("NDArrayInfo for the NDArray object:\n");/**      size_t nElements;      //总元素数目int bytesPerElement;   //每个元素所用字节size_t totalBytes;     //总字节数目NDColorMode_t colorMode;int xDim;int yDim;int colorDim;size_t xSize;size_t ySize;size_t colorSize;size_t xStride;size_t yStride;size_t colorStride;* */printf("nElements: %lu,\tbytesPerElement:%d\ttotalBytes: %lu\n", info.nElements, info.bytesPerElement, info.totalBytes);printf("colorMode: %d\n", info.colorMode);printf("xDim:%d,\tyDim:%d,\tcolorDim:%d\n", info.xDim, info.yDim, info.colorDim);printf("xSize:%lu,\tySize:%lu,\tcolorSize:%lu\n", info.xSize, info.ySize, info.colorSize);printf("xStride:%lu\tyStride:%lu,\tcolorStride:%lu\n", info.xStride, info.yStride, info.colorStride);delete pNDArray;return 0;
}

编译以上源文件进行测试,结果如下:

root@orangepi5:/home/orangepi/C_program/host_program/hostApp# O.linux-aarch64/testNDArrayNDArray  Array address=0x55902dda30:ndims=2 dims=[3 5 ]dataType=4, dataSize=60, pData=0x55902ddc90uniqueId=0, timeStamp=1065510588.289565, epicsTS.secPastEpoch=0, epicsTS.nsec=0referenceCount=1number of attributes=0NDAttributeList: address=0x55902ddbd0:number of attributes=0
array data Information:
0       1       2
3       4       5
6       7       8
9       10      11
12      13      14NDArrayInfo for the NDArray object:
nElements: 15,  bytesPerElement:4       totalBytes: 60
colorMode: 0
xDim:0, yDim:1, colorDim:0
xSize:3,        ySize:5,        colorSize:0
xStride:1       yStride:3,      colorStride:0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/109358.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vscode调试container(进行rocksdb调试)

vscode调试container&#xff08;进行rocksdb调试&#xff09; 参考链接&#xff1a; https://blog.csdn.net/qq_29809823/article/details/128445308#t5 https://blog.csdn.net/qq_29809823/article/details/121978762#t7 使用vscode中的插件dev containners->点击左侧的…

git学习——第4节 时光机穿梭

我们已经成功地添加并提交了一个readme.txt文件&#xff0c;现在&#xff0c;是时候继续工作了&#xff0c;于是&#xff0c;我们继续修改readme.txt文件&#xff0c;改成如下内容&#xff1a; Git is a distributed version control system. Git is free software. 现在&…

游戏中的随机——“动态平衡概率”算法

前言 众所周知计算机模拟的随机是伪随机&#xff0c;但在结果看来依然和现实中的随机差别不大。 例如掷硬币&#xff0c;连续掷很多很多次之后&#xff0c;总有连续七八十来次同一个面朝上的情况出现&#xff0c;计算机中一般的随机函数也能很好模拟这一点。 但在游戏中&…

Android Studio gradle手动下载配置

项目同步时&#xff0c;有时候会遇到Android Studio第一步下载gradle就是连接失败的问题。 这种情况&#xff0c;我们可以手动去gradle官网下载好gradle文件&#xff0c;放置在Android Studio的缓存目录下&#xff0c;这样AS在同步代码时就会自动解压下载好的文件。 步骤如下&…

6.SNMP报错-Error opening specified endpoint “udp6:[::1]:161“处理

启动SNMP服务 /etc/init.d/snmpd start 出现以下报错信息 [....] Starting snmpd (via systemctl): snmpd.serviceJob for snmpd.service failed because the control process exited with error code. See "systemctl status snmpd.service" and "journalctl…

有什么手机软件能分离人声和音乐?

很多人在制作混剪视频&#xff0c;需要二次创作的时候&#xff0c;就经常会把人声分离、背景音乐伴奏提取出来&#xff0c;然后重新加入自己的创意跟想法。下面就一起来看看如何用手机软件分离人声和音乐的吧&#xff01; 音分轨 一款可以分离人声和背景音乐的手机软件&#x…

eNSP笔记①

关闭范文信息&#xff1a;undo terminal monitor VRP三种试图 "<>"表示用户视图&#xff0c;系统默认的状态。主要用于查询设备基础信息或者状态等&#xff0c;也可以执行保存(save)。 “[]” 表示系统视图&#xff0c;在用户视图下输入system-view进入状态…

R语言进度条:txtProgressBar功能使用方法

R语言进度条使用攻略 在数据处理、建模或其他计算密集型任务中&#xff0c;我们常常会执行一些可能需要很长时间的操作。 在这些情况下&#xff0c;展示一个进度条可以帮助我们了解当前任务的进度&#xff0c;以及大约还需要多长时间来完成&#xff0c;R语言提供了几种简单且灵…

Excel提高工作效率常用功能

定位快捷键使用 CtrlG或者F5 根据不同类别插入空行 例&#xff1a;以下表&#xff0c;以部门为单位&#xff0c;每个部门后插入空白行 部门姓名出勤基本工资岗位津贴公体加班绩效基数工龄应发合计财务部姓名73115002101710财务部姓名11116006003401502363财务部姓名5271000…

【微信小程序】6天精准入门(第4天:自定义组件及案例界面)

一、自定义组件 1、介绍 从小程序基础库版本 1.6.3 开始&#xff0c;小程序支持简洁的组件化编程。所有自定义组件相关特性都需要基础库版本 1.6.3 或更高。 开发者可以将页面内的功能模块抽象成自定义组件&#xff0c;以便在不同的页面中重复使用&#xff1b;也可以将复杂的页…

maven 编译.../maven-metadata.xml 报错

文章目录 问题解决 问题 突然编译报错: 解决 打开maven的里离线工作模式,感觉就是下载包到本地. 一个是在maven设置里面 或者直接在maven编译的窗口:

游戏设计模式专栏(十二):在Cocos游戏开发中运用代理模式

点击上方亿元程序员关注和★星标 引言 大家好&#xff0c;我是亿元程序员&#xff0c;一位有着8年游戏行业经验的主程。 本系列是《和8年游戏主程一起学习设计模式》&#xff0c;让糟糕的代码在潜移默化中升华&#xff0c;欢迎大家关注分享收藏订阅。 代理模式&#xff08…

HTML 表格及练习

表格 概述 表格是一种二维结构&#xff0c;横行纵列。 由单元格组成。 表格是一种非常“强” 的结构&#xff1a; 每一行有相同的列数&#xff08;单元格&#xff09;&#xff0c;每一列有相同的行数&#xff08;单元格&#xff09; 同一列的单元格&#xff0c;宽度&#…

Windows + Msys 下编译 TensorFlow 2.14

安装基本工具 宁滥毋缺 pacman -S --needed base-devel pacman -S --needed vim tar wget unzip protobufpacman -S --needed mingw-w64-x86_64-cmake \mingw-w64-x86_64-gcc \mingw-w64-x86_64-toolchain \mingw-w64-x86_64-boost \mingw-w64-x86_64-ccache \mingw-w64-x86…

持续集成部署-k8s-资源调度:DaemonSet

持续集成部署-k8s-资源调度:DaemonSet 1. DaemonSet 简介2. 部署 Fluent 日志收集程序1. DaemonSet 简介 在 Kubernetes 中,DaemonSet 是一种用于在集群中运行一个 Pod 副本的控制器对象。它可以保证在每个节点上都运行一个 Pod 副本,并且在节点加入或退出集群时自动地更新…

2023 年值得关注的软件测试趋势(3)

16.云性能工程对业务连续性的影响 检查和改进基于云的应用程序和服务的性能是云性能工程的主要目标&#xff0c;是各种软件测试趋势中云计算的重要组成部分。云提供了无与伦比的可扩展性、灵活性和成本节约&#xff0c;但如果没有适当的性能工程&#xff0c;组织将面临应用程序…

太好上手了!10款常用的可视化工具你一定要知道!

当谈到可视化工具时&#xff0c;有许多常用的工具可供选择。这些工具可以帮助我们将数据转化为易于理解和具有视觉吸引力的图表、图形和仪表板。 以下是10款常用的可视化工具&#xff0c;它们在不同领域和用途中广泛使用。 1. Datainside&#xff1a; Datainside是一款功能强…

Win+L不能锁屏

1、运行WINR&#xff0c;输入REGEDIT&#xff0c;运行注册表&#xff1a; 2、CTRLF&#xff0c;输入查找DisableLockWorkstation 3、双击这个&#xff0c;点十进制&#xff0c;输入0点确认即可。

Confluence 自定义博文列表

1. 概述 Confluence 自有博文列表无法实现列表自定义功能&#xff0c;实现该需求可采用页面中引用博文宏标签控制的方式 2. 实现方式 功能入口&#xff1a; Confluence →指定空间→创建页面 功能说明&#xff1a; &#xff08;1&#xff09;页面引用博文宏 &#xff08;…

基于安卓Android的掌上酒店预订APP

项目介绍 网络的广泛应用给生活带来了十分的便利。所以把掌上酒店预订与现在网络相结合&#xff0c;利用java技术建设掌上酒店预订APP&#xff0c;实现掌上酒店预订的信息化。则对于进一步提高掌上酒店预订发展&#xff0c;丰富掌上酒店预订经验能起到不少的促进作用。 掌上酒…