我想在纯Lua中创建一个函数,它从一个数字生成一个分数(23位),一个指数(8位)和一个符号(1位),这样数字大约等于math.ldexp(fraction, exponent - 127) * (sign == 1 and -1 or 1),然后打包生成的值为32位.
数学库中的某个功能引起了我的注意:
frexp函数将浮点值(v)分解为尾数(m)和指数(n),使得m的绝对值大于或等于0.5且小于1.0,并且v = m*2 ^ N.
请注意,math.ldexp是反向操作.
但是,我想不出任何正确打包非整数的方法.由于此函数返回的尾数不是整数,我不确定是否可以使用它.
有没有什么有效的方法可以做类似于math.frexp()返回整数作为尾数的东西?或者是否有更好的方法在Lua中以IEEE754单精度浮点格式打包数字?
先感谢您.
编辑
我在此提出我所做的功能的(希望)最终版本:
function PackIEEE754(number)
if number == 0 then
return string.char(0x00, 0x00, 0x00, 0x00)
elseif number ~= number then
return string.char(0xFF, 0xFF, 0xFF, 0xFF)
else
local sign = 0x00
if number < 0 then
sign = 0x80
number = -number
end
local mantissa, exponent = math.frexp(number)
exponent = …Run Code Online (Sandbox Code Playgroud) 我的目标是在多个程序之间发送/共享数据.这些是我想到的选项:
我选择了最后一个.
那么,将数据从一个程序发送到另一个程序的有效方法是什么?它可能会使用一个缓冲,例如,写字节,并等待reciever标记的第一个字节为"已读" (基本上什么比写入的字节别的),然后重新写的,但在那里我会放在缓冲区,我怎样才能让两个程序都可以访问它?或者也许其他东西也可以起作用?
我用linux.
我正在使用Mozilla Firefox的控制台在博客上运行一些JavaScript,以便对其进行有组织的转储,并将其存储为字符串变量.该字符串包含大约5000条消息,因此它很长.我想以某种方式在计算机上保存这个字符串; 这部分可以使用JavaScript之外的方法在外部完成.
我想到以下选项:
但是,我不知道如何在JavaScript中执行1和2,字符串对于选项3和4来说太长了(3我抱怨当我扩展它时字符串太大,4被截断),而我不知道该怎么做5.
有什么建议?先感谢您.
我注意到如果我使用Microsoft Visual Studio Express 2013在C++中执行类似的操作:
namespace LogLevelEnum {
enum Type {
ALL,
FINEST,
FINE,
INFO,
WARNING,
SEVERE,
OFF
};
}
typedef LogLevelEnum::Type LogLevel;
Run Code Online (Sandbox Code Playgroud)
我可以访问枚举喜欢使用的东西的物品LogLevel::INFO和LogLevel::WARNING,而不是简单地做INFO或WARNING.我喜欢这种方式,因为它没有在包含的命名空间中放置尽可能多的符号.
但是,我想知道这是否是标准行为.我知道可以使用::运算符对类和名称空间进行索引,但是对于枚举也是如此,因为它们只是将所有内容转储到它所在的命名空间中.
我将我的数据保存在程序的可执行文件中.我将它复制到一个临时文件,覆盖从"魔术字符串"开始的部分并将其重命名为原始文件.我知道这是个坏主意,但我只是为了试验而做.
到目前为止,我已经完成了所有工作,除了每次更换文件时我必须重新启用"允许作为可执行文件运行".有什么方法可以解决这个问题?
附加信息:我使用linux.
在使用Visual Studio 2013的C++编译器时,我注意到我的代码依赖于size_t正确编译,甚至没有包含任何定义它的头(即#include <stddef.h>或#include <string.h>).
我测试了这个,因为我有点像不包括整个标题的想法只是为了那些微不足道的事情; 我觉得它膨胀了我的代码.我得出结论size_t,即使代码中没有任何头部包含,Visual Studio 2013的C++编译器也会自动定义.
在享受这一点的同时,我开始担心可移植性.编码方便,感觉像我的代码优雅,对我来说比绝对可移植性更重要; 但我还是喜欢一些便携性.例如,我不介意使用,#pragma once因为大多数编译器支持它并且标题保护是麻烦(特别是在Visual Studio中),但我绝不会因为一个编译器支持它而导致导出模板.
所以,我的问题是,size_t的自动定义是许多编译器提供的广泛特性,还是微软编译器特有的东西?
我刚刚用g ++(4.7)检查了一个包含几十个虚方法的类的大小,因为我听说指针用于虚方法,我认为这将是一个糟糕的实现,因为它会占用80个字节的每个实例在我的系统上只有10个虚拟方法的类.
令我宽慰的是,sizeof(<insert typename here>)只返回了8个字节,即我系统上指针的大小.我认为这意味着它存储了一个指向vtable的指针,而不是每个方法,我只是误解了人们在说什么(或者大多数编译器都是愚蠢的).
然而,在我最终测试之前,我一直在努力使用虚拟方法作为我期望它们工作的方式的指针.我注意到地址实际上是一个相对非常低的数字,通常在100以下,与其他地址相比有8个字节的差异,所以我认为它是某种数组的索引.然后我开始思考如何自己实现vtable,并且不会使用指针,因为我的测试结果清楚地表明了.我很惊讶地发现它使用了整整8个字节(我通过插入一个char字段验证它是否只是填充,后者返回16个字节的sizeof).
相反,我会通过存储一个数组索引(例如4个字节,如果使用具有虚拟方法的65536或更少的类,甚至2个)来实现它,这将在包含指向vtable的指针的查找表中进行搜索,并查找就这样.那么为什么存储指针?出于性能原因,他们只是简单地重用了32位操作系统的代码(因为那里的内存大小没有差别)?
先感谢您.
编辑:
有人要我计算保存的实际内存,我决定编写一个代码示例.不幸的是,它变得非常大(他们要求我在两者中使用10个虚拟方法),但我测试了它,它确实有效.它来了:
#include <cstdio>
#include <cstdlib>
/* For the singleton lovers in this community */
class VirtualTableManager
{
unsigned capacity, count;
void*** vtables;
public:
~VirtualTableManager() {
delete vtables;
}
static VirtualTableManager& getInstance() {
static VirtualTableManager instance;
return instance;
}
unsigned addElement(void** vtable) {
if (count == capacity)
{
vtables = (void***) realloc(vtables, (capacity += 0x2000) * sizeof(void**)); /* Reserves an extra 64KiB of pointers */
}
vtables[count] = vtable;
return …Run Code Online (Sandbox Code Playgroud) 我的目标是在类中更改值时触发事件接收器.我的解决方案是使用get和set函数.但是,我不希望在读取值时出现任何性能问题.在下面的课程中:
class Vertex {
public:
const double& GetX() { return _x; } // should inline automatically
const double& GetY() { return _y; } // ' ' ' '
void SetX(const double& x); // complex stuff in source file
void SetY(const double& y); // ' ' ' '
private:
double _x, _y;
}
Run Code Online (Sandbox Code Playgroud)
我把getter的定义放在头文件中,因为这应该允许它们被内联.
我的问题是:有什么方法可以在更改值时自动调用函数,而不需要在头文件中包含函数定义?或者是否有可见性级别允许任何人读取数据,但只有类本身才能修改它?或者别的什么?
我知道另一种方法是手动调用更新函数,但这看起来很难看:
vertex.X = 5;
vertex.Update();
Run Code Online (Sandbox Code Playgroud)
先感谢您.
编辑:
到目前为止,我听到了一些很棒的答案.解决方案取决于您的目标:
但是,效率怎么样?
我刚刚为我之前推测的单独的读/写访问权限制定了一个很好的技巧:
class Vertex {
public:
Vertex(double x, double y)
: _x(x), _y(y), X(_x), …Run Code Online (Sandbox Code Playgroud) 我想在运行时使用测试来确定字节序,以便我可以确定移位的行为,并注意到我的编译器有点奇怪的优化.这表明它将运行的机器的字节序在编译时是已知的.
这是我定时的两个例程.使用const的例程2大约快了33%.
/* routine 1 */
int big_endian = 1 << 1;
for (register int i = 0; i < 1000000000; ++i) {
int value = big_endian ? 5 << 2 : 5 >> 2;
value = ~value;
}
/* routine 2 */
const int big_endian = 1 << 1;
for (register int i = 0; i < 1000000000; ++i) {
int value = big_endian ? 5 << 2 : 5 >> 2;
value = ~value;
}
Run Code Online (Sandbox Code Playgroud)
例程2的速度与使用在编译时可计算的常量表达式的速度相匹配.如果换班的行为取决于处理器,这怎么可能?
此外,在一个侧面说明,为什么我们调用与最终数目至少 …
c++ ×7
linux ×2
optimization ×2
bit-shift ×1
buffer ×1
endianness ×1
enums ×1
events ×1
executable ×1
firefox ×1
gcc ×1
ieee-754 ×1
javascript ×1
lua ×1
namespaces ×1
pack ×1
size ×1
size-t ×1
standards ×1
stream ×1
string ×1
vertex ×1
vtable ×1