如何将十进制数(浮点数)舍入到最接近的整数?

e.g。

1.2 = 1
1.7 = 2
有帮助吗?

解决方案

输出 perldoc -q round

Perl有round()函数吗?那么ceil()和floor()怎么样? Trig功能?

请记住, 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 <中进行了三角测量/ A> 模块。使用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位机器)的工作方式与数学整数非常相似。 其他数字不保证。

其他提示

虽然不同意关于中途商标等的复杂答案,但对于更常见的(也可能是微不足道的)用例:

my $ rounded = int($ float + 0.5);

<强>更新

如果您的 $ float 可能为负数,则以下变体将产生正确的结果:

my $ rounded = int($ float + $ float / abs($ float * 2 || 1));

通过这个计算,-1.4被舍入为-1,-1.6到-2,零将不会爆炸。

您可以使用 Math :: Round 等模块:

use Math::Round;
my $rounded = round( $float );

或者你可以粗暴地做到这一点:

my $rounded = sprintf "%.0f", $float;

如果您决定使用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

请参阅 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发行版的一部分)&gt;实现三角函数。

     

在内部,它使用 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位机器)的工作方式与数学整数非常相似。   其他数字不保证。

您不需要任何外部模块。

$x[0] = 1.2;
$x[1] = 1.7;

foreach (@x){
  print 

您不需要任何外部模块。

<*>

我可能错过了你的观点,但我认为这是做同样工作的更干净的方法。

这样做是为了遍历元素中的每个正数,以您提到的格式打印数字和舍入整数。代码仅根据小数连接相应的舍入正整数。 int($ _)基本上向下数字所以($ -int($ ))捕获小数。如果小数(按定义)严格小于0.5,则舍入数字。如果没有,请加1来进行综合。

.' = '.( ( (

您不需要任何外部模块。

<*>

我可能错过了你的观点,但我认为这是做同样工作的更干净的方法。

这样做是为了遍历元素中的每个正数,以您提到的格式打印数字和舍入整数。代码仅根据小数连接相应的舍入正整数。 int($ _)基本上向下数字所以($ -int($ ))捕获小数。如果小数(按定义)严格小于0.5,则舍入数字。如果没有,请加1来进行综合。

-int(

您不需要任何外部模块。

<*>

我可能错过了你的观点,但我认为这是做同样工作的更干净的方法。

这样做是为了遍历元素中的每个正数,以您提到的格式打印数字和舍入整数。代码仅根据小数连接相应的舍入正整数。 int($ _)基本上向下数字所以($ -int($ ))捕获小数。如果小数(按定义)严格小于0.5,则舍入数字。如果没有,请加1来进行综合。

))<0.5) ? int(

您不需要任何外部模块。

<*>

我可能错过了你的观点,但我认为这是做同样工作的更干净的方法。

这样做是为了遍历元素中的每个正数,以您提到的格式打印数字和舍入整数。代码仅根据小数连接相应的舍入正整数。 int($ _)基本上向下数字所以($ -int($ ))捕获小数。如果小数(按定义)严格小于0.5,则舍入数字。如果没有,请加1来进行综合。

) : int(

您不需要任何外部模块。

<*>

我可能错过了你的观点,但我认为这是做同样工作的更干净的方法。

这样做是为了遍历元素中的每个正数,以您提到的格式打印数字和舍入整数。代码仅根据小数连接相应的舍入正整数。 int($ _)基本上向下数字所以($ -int($ ))捕获小数。如果小数(按定义)严格小于0.5,则舍入数字。如果没有,请加1来进行综合。

)+1 ); print "\n"; }

我可能错过了你的观点,但我认为这是做同样工作的更干净的方法。

这样做是为了遍历元素中的每个正数,以您提到的格式打印数字和舍入整数。代码仅根据小数连接相应的舍入正整数。 int($ _)基本上向下数字所以($ -int($ ))捕获小数。如果小数(按定义)严格小于0.5,则舍入数字。如果没有,请加1来进行综合。

以下内容将正数或负数舍入到给定的小数位:

sub round ()
{
    my ($x, $pow10) = @_;
    my $a = 10 ** $pow10;

    return (int($x / $a + (($x < 0) ? -0.5 : 0.5)) * $a);
}

以下是五种不同的值汇总方法的示例。第一种是执行求和(和失败)的天真方式。第二次尝试使用 sprintf(),但它也失败了。第三个成功使用 sprintf(),而最后两个(第4和第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 的依赖性

否定数字可能会增加人们需要注意的一些怪癖。

printf 式方法为我们提供了正确的数字,但它们可能导致一些奇怪的显示。我们发现这种方法(在我看来,愚蠢地)放入 - 符号,无论它是否应该。例如,-0.01舍入到一个小数位返回-0.0,而不是0.如果要执行 printf 样式方法,并且您知道不需要小数,请使用 %d 而不是%f (当你需要小数时,就是当显示变得不稳定时)。

虽然这是正确的,但数学没什么大不了的,显示它看起来很奇怪,显示类似“-0.0”的东西。

对于int方法,负数可以改变你想要的结果(尽管有一些参数可以使它们正确)。

int + 0.5 会导致带有负数的实际问题,除非你希望它以这种方式工作,但我想大多数人都没有。 -0.9应该可以舍入到-1,而不是0.如果你知道你想要负数是一个上限而不是一个地板那么你可以在一个单行中执行它,否则,你可能想要使用int方法和一个小的修改(这显然只能回到整数:

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

如果您只关心从整个浮点数(即12347.9999或54321.0001)中获取整数值,这种方法(从上面借用和修改)将起到作用:

my $rounded = floor($float + 0.1); 
cat table |
  perl -ne '/\d+\s+(\d+)\s+(\S+)/ && print "".**int**(log($1)/log(2))."\t$2\n";' 
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top