比较

if (fabs(m1 - m2) < DBL_EPSILON)
{
//相等
}

精度

ref.

以一个四字节整数int n;为例,一共有32位,取值范围是 [-2147483648‬, 2147483647] ,一共是4,294,967,296种可能

float 7位小数精度 使用 4 字节存储
double 16位小数精度 使用 8 字节存储

float的存储正是将4字节32位划分为了3部分来分别存储正负号,小数部分和指数部分的:

  • Sign(1位):用来表示浮点数是正数还是负数,0表示正数,1表示负数。
  • Exponent(8位):指数部分。即上文提到数字c,但是这里不是直接存储c,为了同时表示正负指数以及他们的大小顺序,这里实际存储的是c+127。
  • Mantissa(23位):尾数部分。也就是上文中提到的数字b。
20200603_092245.png 20200603_092308.png

github

string str = fmt::format("{:06.3f}", 0.23456);
// Output: 00.235

std::vector<int> v = {1, 2, 3};
str = fmt::format("{}", fmt::join(v, ", "));
// Output: "1, 2, 3"

@app.route('/')
def index():
return render_template('/index.html', name='zhangsan')

# 页面接收
<a>{{ name }}</a>

传递一个数组

@app.route('/')
def index():
num = ['tom', 'mike', 'amuxia', 'zhao', 'lisi']
return render_template('/index.html', num=num)


# 遍历
<ul>
{% for name in num %}
<li>{{ name }}</li>
{% endfor %}
</ul>

# 过滤
<ul>
{% for name in num %}
<li>{{ name|upper }}</li>
{% endfor %}
</ul>

常用的几个过滤器
capitalize:字符串首字母大学,其余小写。
trim:去空格。
lower:转小写。
upper:转大写。

判断

<!doctype html>
<title>Flaskr</title>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<div class=page>
<h1>Flaskr</h1>
<div class=metanav>
{% if not session.logged_in %}
<a href="{{ url_for('login') }}">log in</a>
{% else %}
<a href="{{ url_for('logout') }}">log out</a>
{% endif %}
</div>
{% for message in get_flashed_messages() %}
<div class=flash>{{ message }}</div>
{% endfor %}
{% block body %}{% endblock %}
</div>

lua_pcall(lua_State *L,int nargs,int nresults,int errfunc)

nargs 参数个数
nresults 返回值个数
errFunc 错误处理函数,0表示无,表示错误处理函数在栈中的索引

--test.lua
function test(x,y)
return x + y
end
lua_loadfile(L,"test.lua");

--调用
lua_pushnumber(L,10); --x 值入栈
lua_pushnumber(L,20); --y 值入栈
lua_pcall(L,2,1,0);

如果没有错误此时栈顶的值为30
如果运行出错,lua_pcall会返回一个非零的结果,如果指定了错误处理函数会先调用错误处理函数,然后再将错误信息入栈,在将返回结果和错误信息入栈之前会先将函数和参数从栈中移除。错误处理函数必须在被调用函数和其他参数之前入栈

所有函数都不是线程安全的

// 发送队列锁
std::mutex m_mutex_write;
// 发送队列
std::queue< std::pair<std::shared_ptr<unsigned char[]>, DWORD> > m_queWrite;


std::shared_ptr<BYTE[]> spBuf(new BYTE[length]);
memcpy(spBuf.get(), data, length);

std::lock_guard<std::mutex> lock(m_mutex_write);
m_queWrite.push(make_pair(spBuf,length));

对CPU密集型代码(比如循环计算) - 多进程效率更高
对IO密集型代码(比如文件操作,网络爬虫) - 多线程效率更高。

th.setDaemon(True)守护线程

python中得thread的一些机制和C/C++不同:在C/C++中,主线程结束后,其子线程会默认被主线程kill掉。而在python中,主线程结束后,会默认等待子线程结束后,主线程才退出。

那么尴尬的问题就出现了,有一种情况,比如说在linux系统中存在脱离于终端的线程,即父进程在创建子进程之后先于子进程退出,会造成这个子进程变为“孤儿进程”

如果你忘记杀死子线程,那么好了,你杀主线程的时候其就会挂起等待直至子线程结束,所以为了避免这样的情况,python有两个函数管理线程:join和setDaemon

join:如在一个线程B中调用threada.join(),则threada结束后,线程B才会接着threada.join()往后运行。
setDaemon:主线程A启动了子线程B,调用b.setDaemaon(True),则主线程结束时,会把子线程B也杀死,与C/C++中得默认效果是一样的。

tkinter

tkinter 可以传入 控件对象到线程中,用于更新界面

self.frameOutput.pack(side=tk.TOP, fill=tk.BOTH, expand=1, pady=4)
self.frameReport.pack_forget()
thrd = threading.Thread(target=dbService.check_data,args=(self.textOutput,))
thrd.setDaemon(True) # 守护线程
thrd.start()
阅读全文 »

website

conda install pyserial
or
pip3 install pyserial

readline

readline 需要 \n 结尾

import serial

def simulate_DL_RS1A():
try:
# 端口,GNU / Linux上的/ dev / ttyUSB0 等 或 Windows上的 COM3 等
port = "COM2"
# 波特率,标准值之一:50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400,57600,115200
baudrate = 19200
# 超时设置,None:永远等待操作,0为立即返回请求结果,其他值为等待超时时间(单位为秒)
timeout = 5
ser = serial.Serial(port, baudrate, timeout=timeout)
# 循环读取数据
while True:
line = ser.readline().decode("gbk")
if line.startswith('M0\r\n'):
result = ser.write("M0,-00.029,+00.043,+00.056,-00.038,+00.037,+00.018,-00.229,+00.030\r\n".encode("gbk"))
pass

# 写数据
result = ser.write("123456".encode("gbk"))
print("字节数:", result)
ser.close() # 关闭串口
except Exception as e:
import traceback
traceback.print_exc()
errMsg = traceback.format_exc()
print("Error: 异常,无法发送邮件: " + errMsg)
except:
import traceback
traceback.print_exc()
errMsg = traceback.format_exc()
print("Error: 未知异常,无法发送邮件: " + errMsg)
pass

read

read(size=1)
Parameters: size – Number of bytes to read.
Returns: Bytes read from the port.
Return type: bytes
Read size bytes from the serial port. If a timeout is set it may return less characters as requested. With no timeout it will block until the requested number of bytes is read.

Changed in version 2.5: Returns an instance of bytes when available (Python 2.6 and newer) and str otherwise.

路径处理

doc

#include <filesystem>
using namespace std::filesystem;

// 这个坑货,快捷方式启动的时候,路径不对了
fs::path p = fs::current_path();
阅读全文 »

sol2
这个目前看比较适合

lua 直接包含源码进来就可以了,不用编译成库。
下面是一个小例子

function sum(x, y)
return x + y
end
#include <lua/lua.hpp>

int LuaHelper::test(int x, int y)
{
string strErr;
lua_State* L = luaL_newstate();
if (luaL_loadfile(L, "sum.lua") || lua_pcall(L, 0, 0, 0)) {
strErr = "Error: failed to load sum.lua";
return 0;
}

lua_getglobal(L, "sum");
lua_pushnumber(L, x);
lua_pushnumber(L, y);

lua_pcall(L, 2, 1, 0);

int result = (int)lua_tonumber(L, -1);
lua_pop(L, 1);
return result;
}

读取 lua 数据

void lua_pushnil      (lua_State *L);
void lua_pushboolean (lua_State *L, int bool);
void lua_pushnumber (lua_State *L, lua_Number n);
void lua_pushinteger (lua_State *L, lua_Integer n);
void lua_pushlstring (lua_State *L, const char *s, size_t len);
void lua_pushstring (lua_State *L, const char *s);

全局变量

C 接口

int lua_getglobal (lua_State *L, const char *name);
Pushes onto the stack the value of the global name. Returns the type of that value.

void lua_setglobal (lua_State *L, const char *name);
Pops a value from the stack and sets it as the new value of global name.

cpp 读取 lua 表

if (lua_istable(m_luaState,-1))
{
// Push another reference to the table on top of the stack (so we know
// where it is, and this function can work for negative, positive and
// pseudo indices
lua_pushvalue(m_luaState, -1);
// stack now contains: -1 => table
lua_pushnil(m_luaState);
// stack now contains: -1 => nil; -2 => table
while (lua_next(m_luaState, -2))
{
// stack now contains: -1 => value; -2 => key; -3 => table
// copy the key so that lua_tostring does not modify the original
lua_pushvalue(m_luaState, -2);
// stack now contains: -1 => key; -2 => value; -3 => key; -4 => table
string strKey = lua_tostring(m_luaState, -1);
retVar = lua_tonumber(m_luaState, -2);
// pop value + copy of key, leaving original key
lua_pop(m_luaState, 2);
// stack now contains: -1 => key; -2 => table
}

}

栈操作

默认栈空间是 20 个。一般情况下都可以用。

可以使用下面函数检查栈空间是否可用。

-- 返回错误码
int lua_checkstack (lua_State *L, int sz);
-- 返回错误信息
void luaL_checkstack (lua_State *L, int sz, const char *msg);

第一个压栈的元素索引是 1,第二个是 2,以此类推。
引用栈顶元素是 -1,第二个是 -2, 以此类推。

lua_tostring(L, -1) 作为字符串返回栈顶元素

判断栈元素类型,使用一组 lua_is* 函数,* 可以是任何 lua 数据类型。例如:lua_isnil, lua_isnumber, lua_isstring, lua_istable

函数原型如下:
int lua_is* (lua_State *L, int index);

实际上 lua_isnumber 和 lua_isstring 检查的是,能否转换到指定类型。所以 任何数值类型满足字符串类型的判断。

还有个函数 lua_type 可以获取数据类型,每个数据类型都有常量定义:LUA_TNIL, LUA_TBOOLEAN, LUA_TNUMBER, LUA_TSTRING

获取元素个数

获取栈中的元素个数
int lua_gettop (lua_State *L);

放入数据

函数原型:lua_push*
放置 * 元素到栈顶

lua_pushboolean
lua_pushcclosure
lua_pushcfunction
lua_pushfstring
lua_pushinteger
lua_pushlightuserdata
lua_pushliteral
lua_pushlstring (arbitrary strings (char *))
lua_pushnil
lua_pushnumber (double)
lua_pushstring (zero-terminated strings)
lua_pushthread
lua_pushvalue
lua_pushvfstring

放入数组


// 建一个新表 栈高度+1, 栈顶元素是新table
// 创建一个新的table, 并把它放在栈顶. narr和nrec分别指定该table的array部分和hash部分的预分配元素数量
void lua_createtable (lua_State *L, int narr, int nrec)

// 用于设置table元素的方法
void lua_settable (lua_State *L, int index);
void lua_rawset (lua_State *L, int index);

void lua_setfield (lua_State *L, int index, const char *k);
void lua_rawseti (lua_State *L, int index, int n);

类型判断

函数原型:lua_is*

int lua_isstring(lua_State L, int index)
判断index指明位置上的元素是为对应的
类型,这里是string. 如果是则返回1,否则返回0;不会改变栈的大小,内容

获取数据

使用 lua_to* 函数。

int lua_toboolean (lua_State *L, int index);
const char *lua_tolstring (lua_State *L, int index, size_t *len);
lua_State *lua_tothread (lua_State *L, int index);
lua_Number lua_tonumber (lua_State *L, int index);
lua_Integer lua_tointeger (lua_State *L, int index);

lua_tolstring and lua_tothread return NULL for values with incorrect types.
The numeric functions, however, have no way to signal a wrong type, so they simply return zero.

引入的新函数:
lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum);
lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum);

The out parameter isnum returns a Boolean that indicates whether the Lua value was successfully coerced to the desired type.

int  lua_gettop    (lua_State *L);
void lua_settop (lua_State *L, int index);
void lua_pushvalue (lua_State *L, int index);
void lua_rotate (lua_State *L, int index, int n);
void lua_remove (lua_State *L, int index);
void lua_insert (lua_State *L, int index);
void lua_replace (lua_State *L, int index);
void lua_copy (lua_State *L, int fromidx, int toidx);

double LuaHelper::test_var()
{
double result = 0;
string strErr;

/* opens Lua */
lua_State* m_luaState = luaL_newstate();
/* opens the standard libraries */
luaL_openlibs(m_luaState);
if (luaL_loadfile(m_luaState, "sum.lua") || lua_pcall(m_luaState, 0, 0, 0)) {
strErr = lua_tostring(m_luaState, -1);
lua_pop(m_luaState, 1); /* pop error message from the stack */
}
else
{
double up_right1_min = 15.3456;
double up_left1_max = 10.1324;
double up_left1_mean = 10.12;
double down_left1_mean = 7.12;

lua_pushnumber(m_luaState, up_right1_min);
lua_setglobal(m_luaState, "up_right1_min");
lua_pushnumber(m_luaState, up_left1_max);
lua_setglobal(m_luaState, "up_left1_max");


// 获取函数,压入栈中
lua_getglobal(m_luaState, "solve_formula");
// 调用函数,调用完成以后,会将返回值压入栈中,2表示参数个数,1表示返回结果个数。
int iRet = lua_pcall(m_luaState, 0, 1, 0);
if (iRet)
{
// 调用出错
const char* pErrorMsg = lua_tostring(m_luaState, -1);

lua_close(m_luaState);
return -1;
}
if (lua_isnumber(m_luaState, -1)) //取值输出
{
result = lua_tonumber(m_luaState, -1);
string str = fmt::format("{}", result);
lua_pop(m_luaState, 1);
}

}
lua_close(m_luaState);
return result;
}

Lua是动态类型语言,变量不要类型定义,区分大小写。 变量使用 字母或下划线开头,后面加字母,数字或下划线。
Lua中有8个基本类型分别为: nil、 boolean、
number、string、userdata、function、thread和 table。函数 type 可以测试给定变量或者值的类型。

目前使用版本 5.3
数值支持两种类型:64bit integers,双精度浮点类型 floats

根据想编译静态库还是动态库,新建对应的 vs 工程,把 lua 源文件加入进去,编译即可。

注释

-- 两个减号是行注释

--[[
这是块注释
这是块注释
--]]

数值

Lua的数字只有double型,64bits

num = 1024
num = 3.0
num = 3.1416
num = 314.16e-2
num = 0.31416E1
num = 0xff
num = 0x56
阅读全文 »