如何将十进制数(浮点数)四舍五入为最接近的整数?
例如:。
1.2 = 1 1.7 = 2
你可以使用一个模块,比如 < A href = “ http://search.cpan.org/dist/Math-Round”rel = “ noReferrer”> Math: : Round :
use Math::Round; my $rounded = round( $float );
或者你可以用粗糙的方式来做:
my $rounded = sprintf "%.0f", $float;
perldoc -q round输出
perldoc -q round
Perl 有 round ()函数吗? ceil ()和 floor ()怎么样? 三角函数? 请记住,int()只是向 0截断。对于舍入到一定数量的数字,sprintf()或 printf()通常是最容易的 路线。 printf("%.3f", 3.1415926535); # prints 3.142 POSIX模块(标准 Perl 发行版的一部分)实现 ceil(),floor(),以及其他一些数学和三角函数 功能。 use POSIX; $ceil = ceil(3.5); # 4 $floor = floor(3.5); # 3 在5.000至5.003 perls 中,在 Math::Complex中完成三角学 使用5.004,Math::Trig模块(标准 Perl 的一部分) 分销)执行三角函数 使用 Math::Complex模块,一些函数可以从 实轴进入复平面,例如2的逆正弦。 金融应用程序的四舍五入可能产生严重的影响 应准确地指定所使用的舍入方法 不信任任何正在进行四舍五入的系统,可能是有好处的 而是实现所需的舍入函数 你自己。 要了解原因,请注意在中途点仍然存在问题 交替: for ($i = 0; $i < 1.01; $i += 0.05) { printf "%.1f ",$i} 0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7 0.8 0.8 0.9 0.9 1.0 1.0 不要责怪 Perl,就像 C. IEEE 说的那样,我们必须这样做 绝对值为 2**31(on 32位计算机)会像数学整数一样工作。 其他数字不能保证。
请记住,int()只是向 0截断。对于舍入到一定数量的数字,sprintf()或 printf()通常是最容易的 路线。
int()
0
sprintf()
printf()
printf("%.3f", 3.1415926535); # prints 3.142
POSIX模块(标准 Perl 发行版的一部分)实现 ceil(),floor(),以及其他一些数学和三角函数 功能。
POSIX
ceil()
floor()
use POSIX; $ceil = ceil(3.5); # 4 $floor = floor(3.5); # 3
在5.000至5.003 perls 中,在 Math::Complex中完成三角学 使用5.004,Math::Trig模块(标准 Perl 的一部分) 分销)执行三角函数 使用 Math::Complex模块,一些函数可以从 实轴进入复平面,例如2的逆正弦。
Math::Complex
Math::Trig
金融应用程序的四舍五入可能产生严重的影响 应准确地指定所使用的舍入方法 不信任任何正在进行四舍五入的系统,可能是有好处的 而是实现所需的舍入函数 你自己。
要了解原因,请注意在中途点仍然存在问题 交替:
for ($i = 0; $i < 1.01; $i += 0.05) { printf "%.1f ",$i} 0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7 0.8 0.8 0.9 0.9 1.0 1.0
不要责怪 Perl,就像 C. IEEE 说的那样,我们必须这样做 绝对值为 2**31(on 32位计算机)会像数学整数一样工作。 其他数字不能保证。
2**31
见 Perldoc/perlfaq:
请记住,int()只是向0截断 一定数目的数字,sprintf()或 printf()通常是 最简单的路线。 printf("%.3f",3.1415926535); # prints 3.142 POSIX模块(标准 Perl 发行版的一部分) 实现了 ceil()、 floor()以及许多其他数学 还有三角函数。 use POSIX; $ceil = ceil(3.5); # 4 $floor = floor(3.5); # 3 在5.000到5.003 perls 中,三角学在 Math::Complex模块中完成。 在5.004中,Math::Trig模块(标准 Perl 发行版的一部分) > 实现了三角函数。 内部使用 Math::Complex模块,有些函数可以中断 从实轴到复平面,例如2的逆正弦。 金融申请的四舍五入可能产生严重的影响,而四舍五入 在这些情况下,我们应该精确地指明所使用的方法 信任 Perl 正在使用的任何系统舍入,而是实现 舍入函数,你需要自己。 要知道为什么,注意你在中点交替上仍然有问题: for ($i = 0; $i < 1.01; $i += 0.05) { printf "%.1f ",$i } 0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7 0.8 0.8 0.9 0.9 1.0 1.0 不要责怪 Perl,就像 C. IEEE 说的那样,我们必须这样做 绝对值为2 * * 31(on 32位计算机)会像数学整数一样工作。 其他数字不能保证。
请记住,int()只是向0截断 一定数目的数字,sprintf()或 printf()通常是 最简单的路线。
printf("%.3f",3.1415926535); # prints 3.142
POSIX模块(标准 Perl 发行版的一部分) 实现了 ceil()、 floor()以及许多其他数学 还有三角函数。
在5.000到5.003 perls 中,三角学在 Math::Complex模块中完成。
在5.004中,Math::Trig模块(标准 Perl 发行版的一部分) > 实现了三角函数。
内部使用 Math::Complex模块,有些函数可以中断 从实轴到复平面,例如2的逆正弦。
金融申请的四舍五入可能产生严重的影响,而四舍五入 在这些情况下,我们应该精确地指明所使用的方法 信任 Perl 正在使用的任何系统舍入,而是实现 舍入函数,你需要自己。
要知道为什么,注意你在中点交替上仍然有问题:
for ($i = 0; $i < 1.01; $i += 0.05) { printf "%.1f ",$i } 0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7 0.8 0.8 0.9 0.9 1.0 1.0
不要责怪 Perl,就像 C. IEEE 说的那样,我们必须这样做 绝对值为2 * * 31(on 32位计算机)会像数学整数一样工作。 其他数字不能保证。
如果您决定使用 printf 或 sprintf,请注意他们使用的是 一半到一半方法。
foreach my $i ( 0.5, 1.5, 2.5, 3.5 ) { printf "$i -> %.0f\n", $i; } __END__ 0.5 -> 0 1.5 -> 2 2.5 -> 2 3.5 -> 4
cat table | perl -ne '/\d+\s+(\d+)\s+(\S+)/ && print "".**int**(log($1)/log(2))."\t$2\n";'
虽然不反对关于中间标记等的复杂答案,但对于更常见的(可能是琐碎的)用例:
my $rounded = int($float + 0.5);
更新
如果你的 $float可能是负的,下面的变化将产生正确的结果:
$float
my $rounded = int($float + $float/abs($float*2 || 1));
根据这个计算,-1.4被四舍五入为 -1,-1.6被四舍五入为 -2,零不会爆炸。
下面是五种不同的值求和方法的示例。第一种是执行求和的天真方法(但是失败了)。第二种尝试使用 sprintf(),但也失败了。第三个使用 sprintf()成功,而最后两个(第四和第五)使用 floor($value + 0.5)。
floor($value + 0.5)
use strict; use warnings; use POSIX; my @values = (26.67,62.51,62.51,62.51,68.82,79.39,79.39); my $total1 = 0.00; my $total2 = 0; my $total3 = 0; my $total4 = 0.00; my $total5 = 0; my $value1; my $value2; my $value3; my $value4; my $value5; foreach $value1 (@values) { $value2 = $value1; $value3 = $value1; $value4 = $value1; $value5 = $value1; $total1 += $value1; $total2 += sprintf('%d', $value2 * 100); $value3 = sprintf('%1.2f', $value3); $value3 =~ s/\.//; $total3 += $value3; $total4 += $value4; $total5 += floor(($value5 * 100.0) + 0.5); } $total1 *= 100; $total4 = floor(($total4 * 100.0) + 0.5); print '$total1: '.sprintf('%011d', $total1)."\n"; print '$total2: '.sprintf('%011d', $total2)."\n"; print '$total3: '.sprintf('%011d', $total3)."\n"; print '$total4: '.sprintf('%011d', $total4)."\n"; print '$total5: '.sprintf('%011d', $total5)."\n"; exit(0); #$total1: 00000044179 #$total2: 00000044179 #$total3: 00000044180 #$total4: 00000044180 #$total5: 00000044180
请注意,floor($value + 0.5)可以替换为 int($value + 0.5),以消除对 POSIX的依赖。
int($value + 0.5)
您不需要任何外部模块。
$x[0] = 1.2; $x[1] = 1.7; foreach (@x){ print $_.' = '.( ( ($_-int($_))<0.5) ? int($_) : int($_)+1 ); print "\n"; }
我可能没明白你的意思,但我觉得这样做同样的工作要干净得多。
这样做的目的是遍历元素中的每个正数,按照您提到的格式打印数字和四舍五入整数。该代码仅根据小数连接各自的四舍五入正整数。Int ($_)基本上是 四舍五入,所以($- int ($)捕获小数。如果小数(根据定义)严格小于0.5,则四舍五入该数。如果没有,则通过添加1进行综合。
负数会增加一些人们需要注意的怪癖。
printf风格的方法给我们正确的数字,但它们可能导致一些奇数显示。我们已经发现,这种方法(在我看来是愚蠢的)是否应该或不应该放入一个 -符号。例如,-0.01四舍五入到小数点后一位将返回 -0.0,而不仅仅是0。如果您要使用 printf风格的方法,并且您知道不需要小数,那么使用 %d而不是 %f(当您需要小数时,就是显示变得不稳定的时候)。
printf
-
%d
%f
虽然它是正确的,对于数学来说没什么大不了的,但是对于显示来说,显示“-0.0”看起来很奇怪。
对于 int 方法,负数可以改变您想要的结果(尽管有一些参数是正确的)。
int + 0.5会导致真正的问题-负数,除非你希望它这样工作,但我想大多数人不会。-0.9应该四舍五入到 -1,而不是0。如果你知道自己想要的是一个天花板而不是一个地板,那么你可以用一行程序来做,否则,你可能会想要使用 int 方法来做一个小小的修改(这显然只适用于返回整数:
int + 0.5
my $var = -9.1; my $tmpRounded = int( abs($var) + 0.5)); my $finalRounded = $var >= 0 ? 0 + $tmpRounded : 0 - $tmpRounded;
我对 sprintf 的解决方案
if ($value =~ m/\d\..*5$/){ $format =~ /.*(\d)f$/; if (defined $1){ my $coef = "0." . "0" x $1 . "05"; $value = $value + $coef; } } $value = sprintf( "$format", $value );
下列数字将四舍五入到一个给定的小数位:
sub round () { my ($x, $pow10) = @_; my $a = 10 ** $pow10; return (int($x / $a + (($x < 0) ? -0.5 : 0.5)) * $a); }
如果你只关心从整个浮点数中得到一个整数值(即12347.9999或54321.0001) ,这种方法(从上面借用和修改)可以解决这个问题:
my $rounded = floor($float + 0.1);
许多专家建议你自己编写舍入程序,因为你的语言提供的“罐装”版本可能不够精确,或者存在错误。不过,我想他们说的是小数点后很多位,而不仅仅是一、二或三位。考虑到这一点,这里是我的解决方案(尽管不完全符合我的需要是显示美元-过程没有太大的不同,虽然)。
sub asDollars($) { my ($cost) = @_; my $rv = 0; my $negative = 0; if ($cost =~ /^-/) { $negative = 1; $cost =~ s/^-//; } my @cost = split(/\./, $cost); # let's get the first 3 digits of $cost[1] my ($digit1, $digit2, $digit3) = split("", $cost[1]); # now, is $digit3 >= 5? # if yes, plus one to $digit2. # is $digit2 > 9 now? # if yes, $digit2 = 0, $digit1++ # is $digit1 > 9 now?? # if yes, $digit1 = 0, $cost[0]++ if ($digit3 >= 5) { $digit3 = 0; $digit2++; if ($digit2 > 9) { $digit2 = 0; $digit1++; if ($digit1 > 9) { $digit1 = 0; $cost[0]++; } } } $cost[1] = $digit1 . $digit2; if ($digit1 ne "0" and $cost[1] < 10) { $cost[1] .= "0"; } # and pretty up the left of decimal if ($cost[0] > 999) { $cost[0] = commafied($cost[0]); } $rv = join(".", @cost); if ($negative) { $rv = "-" . $rv; } return $rv; } sub commafied($) { #* # to insert commas before every 3rd number (from the right) # positive or negative numbers #* my ($num) = @_; # the number to insert commas into! my $negative = 0; if ($num =~ /^-/) { $negative = 1; $num =~ s/^-//; } $num =~ s/^(0)*//; # strip LEADING zeros from given number! $num =~ s/0/-/g; # convert zeros to dashes because ... computers! if ($num) { my @digits = reverse split("", $num); $num = ""; for (my $i = 0; $i < @digits; $i += 3) { $num .= $digits[$i]; if ($digits[$i+1]) { $num .= $digits[$i+1]; } if ($digits[$i+2]) { $num .= $digits[$i+2]; } if ($i < (@digits - 3)) { $num .= ","; } if ($i >= @digits) { last; } } #$num =~ s/,$//; $num = join("", reverse split("", $num)); $num =~ s/-/0/g; } if ($negative) { $num = "-" . $num; } return $num; # a number with commas added #usage: my $prettyNum = commafied(1234567890); }
使用 Math::BigFloat你可以这样做:
Math::BigFloat
use Math::BigFloat; print Math::BigFloat->new(1.2)->bfround(1); ## 1 print Math::BigFloat->new(1.7)->bfround(1); ## 2
这可以包装在一个子例程中
use Math::BigFloat; sub round { Math::BigFloat->new(shift)->bfround(1); } print round(1.2); ## 1 print round(1.7); ## 2