【问题标题】:How to round to the first left digit for decimal in Perl or Any Language?如何在 Perl 或任何语言中舍入到小数点的左第一位?
【发布时间】:2013-12-12 15:31:00
【问题描述】:

我不确定我是否在标题中清楚地解释了我的问题,基本上我需要这样的 floor/ceil 函数:

sub ceil($num)

ceil(120) = 200
ceil(12) = 20
ceil(1.2) = 2
ceil(0.12) = 0.2
ceil(0.012) = 0.02
ceil(0.00000012) = 0.0000002

同样适用于负数(输入和输出均为负号)

谢谢!

【问题讨论】:

  • Math::SigFigs 呢?
  • 非常感谢。看来这就是我需要的。让我试试

标签: perl numbers rounding


【解决方案1】:
sub floor {
    my $a = shift;
    $a =~ s/([1-9])(\d*)(?:\.\d*)?/$1.("0"x length($2))/e;
    0 + $a;
}

sub ceil {
    my $a = shift;
    my $f = floor($a);
    $f =~ s/([1-9])/1+$1/e if abs($a) > abs($f);
    0 + $f;
}

并测试:

$ perl -E'sub floor {my $a = shift; $a=~s/([1-9])(\d*)(?:\.\d*)?/$1.("0"x length($2))/e; 0+$a} sub ceil {my $a = shift;my $f = floor($a); $f=~s/([1-9])/1+$1/e if abs($a) > abs($f); 0+$f} printf "%10g %10g %10g\n", $_, floor($_), ceil($_) for (120, 12, 1.2, 0.12, 0.012, 200, 20, 0.2, -120, -12, -0.12, -0.2,0, 1.2e12, -1.2e-12)'
       120        100        200
        12         10         20
       1.2          1          2
      0.12        0.1        0.2
     0.012       0.01       0.02
       200        200        200
        20         20         20
       0.2        0.2        0.2
      -120       -100       -200
       -12        -10        -20
     -0.12       -0.1       -0.2
      -0.2       -0.2       -0.2
         0          0          0
   1.2e+12      1e+12      2e+12
  -1.2e-12     -1e-12     -2e-12

【讨论】:

  • Hynek,这真的很酷。我从没想过使用正则表达式来处理这类问题,因为我总是用数学术语来思考数值问题。非常感谢。
  • 如果你想要 2^N 舍入,你可以使用位,但如果你需要 10^N,除了十进制表示,即字符串之外,没有这样的数字表示。所以这对我来说似乎很明显。顺便说一句,如果您需要 2^N ceil:static __inline unsigned clp2(unsigned x) { return x>1?(unsigned)INT32_MIN >> (__builtin_clz(x-1)-1):x; } 和 floor static __inline unsigned flp2(unsigned x) { return 1 << (sizeof(x)*8-1 - __builtin_clz(x)); } 用于 C 中的无符号数字。
【解决方案2】:

这可能有用吗?我没有测试过,但我认为逻辑在那里。

第 1 步我们找到最接近的 10 的幂(将其分配给“$base”)

第 2 步我们确定 $num 是否可以被这个基数整除

如果是步骤 2.1,则返回

步骤 2.2 如果不是,则减去模并加 1

$base = 10*floor(log($num,10));
return ($num % $base)?($num - ($num%$base) + 1):$num;

数学不是我最擅长的,所以可能有更好的方法

【讨论】:

  • 我刚刚意识到这不适用于小于 1 的值(IE:小数),但这是一个开始。我也会想办法适应这些。
  • 谢谢。我也想过记录日志,但也停留在小数点
猜你喜欢
  • 1970-01-01
  • 2014-06-15
  • 2011-11-12
  • 1970-01-01
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多