Optimization 如何将数字的最后3位转换为0

Optimization 如何将数字的最后3位转换为0,optimization,math,Optimization,Math,如何将数字的最后3位转换为0 示例3444678至3444000 我真的很喜欢 (国际)(3444678/1000)*1000=3444000 但除法和乘法可能代价高昂 任何其他解决方案???您可以尝试 n - (n % 1000) 但模运算符可能与除法一样昂贵。在任何情况下,这听起来非常像一个微观优化。这真的是你的瓶颈吗?inttakeaway(intnum) int takeAway(int num) { for (int i = 1; i =< 3; i++) {

如何将数字的最后3位转换为0

示例3444678至3444000

我真的很喜欢

(国际)(3444678/1000)*1000=3444000

但除法和乘法可能代价高昂

任何其他解决方案???

您可以尝试

n - (n % 1000)
但模运算符可能与除法一样昂贵。在任何情况下,这听起来非常像一个微观优化。这真的是你的瓶颈吗?

inttakeaway(intnum)
int takeAway(int num)
{
    for (int i = 1; i =< 3; i++)
    {
        num = num/10;
    }

    return num;
}

int addZeroes(int num)
{
    for (int i = 1; i =< 3; i++)
    {
        num = num*10;
    }

    return num;
}
{ for(int i=1;i=<3;i++) { num=num/10; } 返回num; } int addZeroes(int num) { for(int i=1;i=<3;i++) { num=num*10; } 返回num; }
然后你只需要叫外卖然后加零。再简单不过了


我试图添加一个int temp=num,然后使用它,但我认为这太多了,即使对于这段代码也是如此。

如果您想要舍入到任意精度,并且您的舍入方法缺少精度控制,那么这应该可以工作:

至少在Perl中,mod应该更快 原因如下: 本基准产生的(10**7)*3个随机浮点数样本:

Dividing
Time taken was  7 wallclock secs ( 6.83 usr  0.00 sys +  0.00 cusr  0.00 csys =  6.83 CPU) seconds

Multiplying
Time taken was  7 wallclock secs ( 6.67 usr  0.00 sys +  0.00 cusr  0.00 csys =  6.67 CPU) seconds

Modding
Time taken was  8 wallclock secs ( 7.87 usr  0.00 sys +  0.00 cusr  0.00 csys =  7.87 CPU) seconds

Multiply + Dividing
Time taken was 10 wallclock secs (10.18 usr  0.01 sys +  0.00 cusr  0.00 csys = 10.19 CPU) seconds
但是请注意,
10**7*3
是一个redicle浮点数。我不能使用
10**8
浮点,因为为了公平的测试,我必须对所有测试使用相同的浮点序列,而且很多浮点耗尽了我的4G内存

好的,比特侧主题:/

(Perl实现只使用Int,通常是截断而不是舍入)

使用模数法 如上所述(除了不舍入)使用整数的模方法,但仍然适用于舍入到浮点精度(小数点右侧的精度有点慢)

use strict;
use warnings;
use version;
our $VERSION = qv('0.1');

sub xround {
    my ( $number, $precision ) = @_;
    my $ino = int( $number );
    if ( $precision eq 0 ) {
        return $ino; 
    }
    my $power = 10**$precision;

    if ( $precision > 0 ) {
        return int( $number - ( $number % $power ) );
    }
    return $ino + int( ( $number - $ino ) / $power ) * $power;
}


my $fmt = "%s : %s  ( %s )\n";
my $n = 55555.55555;
for my $i ( -4 .. 4 )
{
    printf $fmt, $n, xround($n, $i), $i; 
}

顺便说一句(你已经在这里得到了很好的输入)

位操作从来都不适用于十进制数。问题是位的值根本不映射到十进制。使用BCD它工作得很好,但从来没有人使用过它(也许BigDecimal会这么做?我对此表示怀疑)

无论如何,你可以使用一个以10为基数的技巧乘以10的因数,但除非你是在1970年代的CPU上编写汇编程序,否则这是不值得的;但仅仅因为它污染了我的内存库,我就把它贴出来供你娱乐:

int mult10(int val) {
    int tmp_2val = val << 1; // double val
    int tmp_8val = val << 3; // 8x val
    return( tmp_2val + tmp_8val ); // 2x + 8x = 10x
}
int mult10(int val){
int tmp_2val=val一个移位技巧,然后:

n >>= 3;
n -= n % (5 * 5 * 5);
n <<= 3;
它乘以某个疯狂的数字(274877907),然后做一些其他的事情,大概更快


这个故事的寓意是:你的代码对编译器的作用越明显,编译器就越有可能以你从未想过的方式对其进行优化。如果代码更容易让人理解,这是另一个好处。

如果你在使用八进制,你可以简单地:

x &= ~0777;
x &= ~0xfff;
如果您正在使用十六进制,您可以简单地:

x &= ~0777;
x &= ~0xfff;
但对于decimal,您可能应该按照Jesse Beder的建议进行:

x -= (x % 1000);
大多数系统都有一个快速整数除法;如果你在一个没有除法的系统上工作,你可以使用该算法快速转换为bcd



根据您尝试执行的其他操作,在将数字转换为可打印(字符串)时,截断可能更容易格式如Avitus所建议。

不,这不是任何瓶颈。我只是想知道是否有一些位操作技巧可以解决这个问题,比如移位运算符或其他东西。这是一个不错的选择,但我担心它太聪明了。原来的方式更清楚你在做什么。另外,正如你所说的,添加/除法是相同的co实际上,我发现它比原来的更可读(因为这取决于整数的截断,这对我来说总是不明显的),但这是一个品味的问题。无论如何,原始版本实际上是乘法/除法,可能比subtract/mod慢一点。乘法/除法肯定比subtract/mod慢。mod通常使用完全相同的电路实现(通常使用完全相同的指令)作为除法,只使用结果的另一半。倍数当然比减法更复杂。18纳秒的除法?这太过分了!光子可能从我的电脑机箱中、从窗口中出来,然后大部分时间都在前面的花园里!这涉及循环,比做(num/1000)更昂贵*1000讽刺在互联网上不起作用。下次试着用笑脸。:)自然。鉴于每个人都说这很好,我觉得有必要提供一个“替代品”。但它确实起作用!理查德,你是在暗示这不是一个玩笑吗?我现在真的很困惑:-(我投了这个票,因为它可能是这里最好的解决方案。可重用且意图明确。当程序员担心简单除法/乘法的性能时,这不是一个好迹象!这意味着他不明白!如果数字是整数,那么除法和乘法不应该太昂贵。确保它们是整数,并确保我认为,这个部门是一个整数除法。我只能猜测你使用的是什么语言,所以不能对适当的语法提出建议。抱歉,我只是注意到一些有用的人删除了你原来在你的问题中包含的C++标签。我真的不明白为什么人们会做那种编辑。是的,不知道为什么人们会编辑标签。我不认为这应该被允许编辑其他人的内容……我知道这个问题需要一个数学解决方案。然而,一个简单的字符串格式解决方案不是最简单、最明显的吗?有时,在一些边缘情况下,微优化会带来好处。特别是在某些方面。我看到了一个3n+1挑战如果你使用二进制编码十进制(BCD),那么也只有这样你才能在base10中进行位运算:)我在回答中提到了BCD。另外,一个带有数学协处理器的系统也应该这样做
x &= ~0xfff;
x -= (x % 1000);