How to convert last 3 digits of number into 0
example 3444678 to 3444000
I can do like
(int)(3444678/1000) * 1000= 3444000
But division and multiplication could be costly...
Any other solution????
How to convert last 3 digits of number into 0
example 3444678 to 3444000
I can do like
(int)(3444678/1000) * 1000= 3444000
But division and multiplication could be costly...
Any other solution????
You could try
n - (n % 1000)
but the modulus operator might be as costly as a division. In any case, this sounds an awful lot like a micro-optimization. Is this really your bottleneck?
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;
}
Then you just call takeAway then addZeroes. Couldn't be simpler!
I was tempted to add in an int temp = num and then use that but figured that would be too much, even for this code.
If you want to round to an arbitrary precision and your round method lacks precision control, this should work:
Heres why: Sample of ( 10 ** 7 ) * 3 random floats produced this benchmark:
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
Do note however that 10 ** 7 * 3
is a REDICULOUS number of floats. I couldn't use 10**8
floats because for a fair test, i had to use the same float sequence for all tests, and that many floats EXHAUSTED MY 4G OF MEMORY
Ok, bit side topic :/
( Perl Implementation using only Int, which truncates instead of rounding normally )
use strict;
use warnings;
use version;
our $VERSION = qv('0.1');
sub xround {
my ( $number, $precision ) = @_ ;
if ( $precision eq 0 )
{
return int( $number + .5 );
}
my $scale = 10 ** abs( $precision ) ;
$number = $number / $scale if $precision > 0;
$number = $number * $scale if $precision < 0;
$number = int( $number + .5 );
$number = $number * $scale if $precision > 0;
$number = $number / $scale if $precision < 0;
return $number;
}
my $fmt = "%s : %s ( %s )\n";
my $n = 55555.55555;
for my $i ( -4 .. 4 )
{
printf $fmt, $n, xround($n, $i), $i;
}
.
55555.55555 : 55555.5556 ( -4 )
55555.55555 : 55555.556 ( -3 )
55555.55555 : 55555.56 ( -2 )
55555.55555 : 55555.6 ( -1 )
55555.55555 : 55556 ( 0 )
55555.55555 : 55560 ( 1 )
55555.55555 : 55600 ( 2 )
55555.55555 : 56000 ( 3 )
55555.55555 : 60000 ( 4 )
This works as above, ( except without rounding ) using modulus method for ints, but still works for rounding into float precision ( with a bit of a slow-down for precisions right of the decimal point.
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;
}
.
55555.55555 : 55555.5555 ( -4 )
55555.55555 : 55555.555 ( -3 )
55555.55555 : 55555.55 ( -2 )
55555.55555 : 55555.5 ( -1 )
55555.55555 : 55555 ( 0 )
55555.55555 : 55550 ( 1 )
55555.55555 : 55500 ( 2 )
55555.55555 : 55000 ( 3 )
55555.55555 : 50000 ( 4 )
Just as a by the way (you've gotten good input here already).
Bit manipulation never works with decimal numbers. The problem is that the values of the bits don't map to decimal at all. With BCD it works great, but nobody ever uses that (maybe BigDecimal does??? I doubt it though).
Anyway, the one base-10 trick you can use is multiplying by factors of 10, but it's never worth while unless you are coding assembly on some 1970's CPU; but just because it's polluting my memory banks, I'll post it for your amusement:
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
}
But the math co-processor can do it so much quicker than that, just NEVER OPTIMIZE! The fact that you even take execution speed into consideration is an issue, and your "optimization" is usually as likely to slow the system down than speed it up.
I believe you can use a similar method to divide by 10, but I'm not going to try to figure it out--it's late--If I remember correctly it has something to do with examining the bits shifted out and adding values back in based on their value.
A shift trick, then:
n >>= 3;
n -= n % (5 * 5 * 5);
n <<= 3;
Is it faster? Doubtful.
But here's a fun fact: gcc doesn't use division/modulus for this:
n -= n % 1000;
It multiplies by some crazy number (274877907) and does some other stuff which is presumably faster.
The moral of this story: the more obvious the purpose of your code is to the compiler, the more likely it is that the compiler will optimise it in a way you'd never think of. If the code is easier for humans to understand, that's another bonus.
If you are working on octal, you can simply:
x &= ~0777;
If you are working on hex, you can simply:
x &= ~0xfff;
But for decimal, you should probably do it the way Jesse Beder suggests:
x -= (x % 1000);
Most systems have a fast integer divide; if you're working on a system that doesn't, you could use the double dabble algorithm to fast convert to bcd. Look at the section about dividing by ten.
Depending on what else you're trying to do, it may be easier to truncate when converting the number to a printable (string) format as Avitus suggested.