我试图优化如下。代码波纹管这样处理:

如果α= 0.775和我需要精度2 DP则a => 0.78

基本上,如果最后的数字是5,它向上舍入下一个数字,否则它不会。

我的问题是,0.45犯规圆至0.5与1个decimalpoint,作为值被保存为0.44999999343 ....和setprecision其四舍五入至0.4。

这就是为什么setprecision被强制为高setprecision(p+10),然后,如果它确实在5结束时,为了正确地舍入添加量小。

一旦这样做,它比较与一个串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;
}
有帮助吗?

解决方案

我写了什么比ASM的一对夫妇十几行的整数的平方根子程序,没有API调用任何 - 它仍然只能做约5000万SqRoots /秒(这是大约五年前...) 。

我做的一点是,如果你去了数十亿的电话,即使在今天的技术是要窒息。

但如果你真的要作出努力,加快步伐,去掉尽可能多的API用法力所能及的。这可能需要您手动执行,而不是让库为你做API任务。具体而言,除去任何类型的流的操作。这些比在这方面的污垢慢。你可能真的要凑合那里。

唯一剩下要做后要替换的C那么多的行++,你可以自定义ASM - 但你必须是一个关于它的完美主义者。确保你所走的每CPU周期的充分利用和注册 - 以及CPU缓存和堆栈空间的每一个字节。

您可以考虑使用整数值代替浮动点,因为这些是远远ASM友好,更加高效。你必须通过10 ^ 7乘以数量(或10 ^ P,这取决于你决定如何形成你的逻辑),以一路过来向右移动小数点。然后,你可以在浮点安全地转换成基本整数。

您将不得不依赖于计算机硬件做休息。

<--Microsoft Specific-->结果 我还要补充一点,C ++标识符(包括静态的,因为甄子丹德波尔提到的)都是直接从嵌套到你的C ++代码ASM块访问。这使得内嵌ASM变得轻而易举。结果 <--End Microsoft Specific-->

其他提示

根据你想要的数字,你可能想使用的,而不是浮点点数。快速搜索变成了href="http://www.codeguru.com/cpp/cpp/algorithms/math/article.php/c12097" rel="nofollow noreferrer">这

我觉得你可以只是为了精确添加0.005至百分之一,0.0005千等的snprintf的东西,如“%1.2F”(百分之一,千分之一1.3F等)的结果和比较字符串。你应该能够表IZE或参数化此逻辑。

您可以通过就是这个双T []静态的,因此,它不是遍地分配它在你的代码发布保存一些重要的周期。

尝试这个代替:

#include <cmath>

double setprecision(double x, int prec) {
    return 
        ceil( x * pow(10,(double)prec) - .4999999999999)
        / pow(10,(double)prec);
}

这可能更快。也许尝试内联一样好,但如果没有帮助,可能会伤害。

它是如何工作示例:

2.345* 100 (10 to the 2nd power) = 234.5
234.5 - .4999999999999 = 234.0000000000001
ceil( 234.0000000000001 ) = 235
235 / 100 (10 to the 2nd power) = 2.35

在0.4999999999999被选择的,因为精度为一个C ++在32位系统上的两倍。如果你是一个64位平台上,你可能需要更多的花枝招展。如果进一步增加在32位系统上的花枝招展溢出和轮代替了下来,我。即234.00000000000001被截断到234在(我的)32位环境双

使用浮点(不精确的表示)意味着你已经损失了约真实数目的一些信息。你不能简单地通过增加软糖值“修复”存储在双重价值。这可能解决某些情况下(如0.45),但它会破坏其他案件。你会最终围捕应该已经四舍五入的数字。

下面是一篇相关的文章: http://www.theregister.co.uk/2006/08/12 / floating_point_approximation /

我走在猜测你真正的意思做。我怀疑你是想看看是否一个字符串包含双的一些精密十进制表示。也许这是一个算术测验程序和你要看到,如果用户的响应是“足够接近”真正的答案。如果是这样的话,那么它可能是简单的字符串转换为双,看看两个双打之间的差异的绝对值是一定误差内。

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();
}

这两个解决方案应该比你的示例代码更快,但我不知道如果他们这样做你真正想要的。

据我看到要检查如果一个圆形的上p个点等于湾

insted的改变字符串的,使其它的方式和变化串加倍 - (只用小桌子乘法和addion或仅additoins) - 然后。减去两个号码,并检查是否是减法在适当的范围内(如果p == 1 => ABS(P-A)<0.05)

从英镑的黑暗时代旧时代开发商招,先令和便士在古老的国家。

诀窍是存储该值作为一个整体数目FO半pennys。 (或任何你的最小单位是)。然后所有的后续arithmatic是直截了当的整数arithimatic和舍入等将照顾自己。

所以你的情况,你保存在任何你指望200ths单位的数据, 做这些值,再除以200简单的整数计算为浮动varaible每当你要显示的结果。

我beleive升压的确是“BigDecimal的”库这些天,但,你对运行时的速度要求可能会排除这种否则优秀的解决方案。

貌似你试图做的是不是真正的圆。 0.45确实0.45在二进制表示法,并且是0.44999999343不是一回事。

可能是你需要做多种舍入 - 先说小数点后3位,然后两个,然后一个

现在的问题是,什么是你想实现什么?如果您的匹配标准是

abs(a-b) < 10 ** -p

代替?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top