C++ C/C++;以一定的精度高效地舍入小数
我试图优化以下内容。下面的代码执行以下操作: 如果a=0.775,我需要精度2 dp,那么a=>0.78 基本上,如果最后一个数字是5,它会向上舍入下一个数字,否则不会 我的问题是0.45不能用1个小数点四舍五入到0.5,因为值保存为0.4499999343。。。。并将精度设置为0.4 这就是为什么setprecision必须更高C++ C/C++;以一定的精度高效地舍入小数,c++,c,optimization,double,decimal,C++,C,Optimization,Double,Decimal,我试图优化以下内容。下面的代码执行以下操作: 如果a=0.775,我需要精度2 dp,那么a=>0.78 基本上,如果最后一个数字是5,它会向上舍入下一个数字,否则不会 我的问题是0.45不能用1个小数点四舍五入到0.5,因为值保存为0.4499999343。。。。并将精度设置为0.4 这就是为什么setprecision必须更高setprecision(p+10)的原因,如果它真的以5结尾,则添加少量以便正确地进行取整 完成后,它将a与字符串b进行比较并返回结果。问题是,这个函数被调用了几十亿
setprecision(p+10)
的原因,如果它真的以5结尾,则添加少量以便正确地进行取整
完成后,它将a与字符串b进行比较并返回结果。问题是,这个函数被调用了几十亿次,使程序崩溃。关于如何重写/优化它,以及代码中哪些函数对机器如此重要,有什么更好的想法吗
bool match(double a,string b,int p) { //p = precision no greater than 7dp
double t[] = {0.2, 0.02, 0.002, 0.0002, 0.00002, 0.000002, 0.0000002, 0.00000002};
stringstream buff;
string temp;
buff << setprecision(p+10) << setiosflags(ios_base::fixed) << a; // 10 decimal precision
buff >> temp;
if(temp[temp.size()-10] == '5') a += t[p]; // help to round upwards
ostringstream test;
test << setprecision(p) << setiosflags(ios_base::fixed) << a;
temp = test.str();
if(b.compare(temp) == 0) return true;
return false;
}
bool匹配(双a,字符串b,int p){//p=精度不大于7dp
双t[]={0.2,0.02,0.002,0.0002,0.00002,0.000002,0.0000002,0.00000002};
细流浅黄色;
字符串温度;
buff根据您想要的数字,您可能希望使用定点数字而不是浮点数。这时出现了一个快速搜索。我编写了一个整数平方根子例程,只包含几十行ASM,没有任何API调用,但它仍然只能执行大约5000万平方根/秒的操作(这是大约五年前……)
我想说的是,如果你要打数十亿个电话,即使是今天的技术也会被扼杀
但是,如果您真的想努力加快速度,请尽可能多地删除API用法。这可能需要您手动执行API任务,而不是让库为您执行。具体来说,请删除任何类型的流操作。在这种情况下,这些操作都比脏操作慢。您可能真的需要在那里即兴发挥
<> P>唯一的事情是在自定义ASM中尽可能多地替换C++行,但是你必须是一个完美主义者。确保你充分利用了每个CPU周期和登记——以及CPU缓存和堆栈空间的每个字节。
你可以考虑使用整型值而不是浮点,因为它们比ASM更友好,效率更高。你必须将数字乘以10 ^ 7(或者10 ^ P,这取决于你决定如何形成逻辑)。将小数点一直向右移动。然后您可以安全地将浮点转换为基本整数
剩下的事你得依靠计算机硬件来做
我还将补充,C++标识符(包括静态的,如Donnie DeBoer所提到的)可以直接从嵌套到C++代码中的ASM块访问。这使得内联ASM成为一种微风。
我认为您可以将精度增加到百分之0.005,千分之0.0005,等等。snprint的结果类似于“%1.2f”(百分之一百,千分之1.3f,等等)并比较字符串。您应该能够将此逻辑表化或参数化。您可以通过将双t[]设置为静态来节省发布代码中的一些主要周期,这样它就不会反复分配它。使用浮点(一种不精确的表示)表示您丢失了一些有关真实数字的信息。您不能简单地通过添加一个伪造值来“修复”存储在double中的值。这可能会修复某些情况(如.45),但会破坏其他情况。您将最终对本应向下舍入的数进行舍入
以下是一篇相关文章:
试试这个:
#include <cmath>
double setprecision(double x, int prec) {
return
ceil( x * pow(10,(double)prec) - .4999999999999)
/ pow(10,(double)prec);
}
< P> 4999999999999是因为32位系统上的C++双精度而选择的。如果你在一个64位的平台上,你可能需要更多的NNIN。如果你在32位系统上增加了NNIN,它会溢出而不是向上循环,也就是说,234.00000000000001在i(i)中被截断到234。32位环境。我在猜测您的真正意图。我怀疑您是在尝试查看字符串是否包含双精度到某种精度的十进制表示形式。也许这是一个算术测验程序,您是在尝试查看用户的响应是否“足够接近”如果是这样的话,那么将字符串转换为double并查看两个double之间的差值的绝对值是否在某个公差范围内可能会更简单
double string_to_double(const std::string &s)
{
std::stringstream buffer(s);
double d = 0.0;
buffer >> d;
return d;
}
bool match(const std::string &guess, double answer, int precision)
{
const static double thresh[] = { 0.5, 0.05, 0.005, 0.0005, /* etc. */ };
const double g = string_to_double(guess);
const double delta = g - answer;
return -thresh[precision] < delta && delta <= thresh[precision];
}
双字符串到双字符串(const std::string&s)
{
std::stringstream缓冲区;
双d=0.0;
缓冲区>>d;
返回d;
}
布尔匹配(常量标准::字符串和猜测、双答案、整数精度)
{
常数静态双阈值[]={0.5,0.05,0.005,0.0005,/*等。*/};
const double g=字符串到双(猜测);
常数双增量=g-答案;
return-thresh[precision]
不要把a改成字符串,换一种方式,把字符串改成双精度
-(仅使用乘法和加法或仅使用小表的加法)
-然后减去两个数字,检查减法是否在适当的范围内(如果p==1=>abs(p-a)<0.05)旧国家的英镑、先令和便士的黑暗时代
诀窍是将值存储为半便士的整数(或任何最小的单位)。然后,所有后续的算术运算都是简单的整数算术运算,取整等将自行处理
因此,在你的情况下,你将数据存储在你正在计算的数据的200分之一的单位中,
对这些值进行简单的整数计算,并在需要显示结果时将其除以200,得到一个浮点变量
我相信Boost现在有一个“BigDecimal”库,但是,您对运行时速度的要求可能会排除这个优秀的解决方案
double string_to_double(const std::string &s)
{
std::stringstream buffer(s);
double d = 0.0;
buffer >> d;
return d;
}
bool match(const std::string &guess, double answer, int precision)
{
const static double thresh[] = { 0.5, 0.05, 0.005, 0.0005, /* etc. */ };
const double g = string_to_double(guess);
const double delta = g - answer;
return -thresh[precision] < delta && delta <= thresh[precision];
}
bool match2(const std::string &guess, double answer, int precision)
{
const static double thresh[] = {0.5, 0.05, 0.005, 0.0005, /* etc. */ };
const double rounded = answer + thresh[precision];
std::stringstream buffer;
buffer << std::setprecision(precision) << rounded;
return guess == buffer.str();
}