如何用“int”,模数和除法简化表达式?

时间:2014-03-04 22:33:48

标签: algorithm perl math

下面的脚本以十进制数计算时差,但是我得到一个舍入误差,所以我猜这是因为我最后的转换很糟糕。

问题

有些东西告诉我,表达式可以简化,但是当我有int,模数和除法时,这个特殊情况下的数学规则是什么?

#!/usr/bin/perl

print f("9:00", "16:45");

sub f {
    my $t1 = shift @_;
    my $t2 = shift @_;

    my $m1 = $1*60+$2 if $t1 =~ m/(\d\d?):(\d\d?)/;
    my $m2 = $1*60+$2 if $t2 =~ m/(\d\d?):(\d\d?)/;

    my $h = int(($m2-$m1)/60);

    return $h + ($h*60+$m2-$m1)%60/60;
}

3 个答案:

答案 0 :(得分:6)

自午夜起已经过了几分钟,您已经正确计算了$m1$m2。那么为什么不简单地以小时为单位返回时差:

return ($m2 - $m1) / 60.0;

就“数学规则”而言,也许有助于查看你的return与我的相比,看看为什么它们是等价的(忽略舍入):

$h + ($h * 60 + $m2 - $m1) % 60 / 60

请注意,($h * 60) % 60为零,因此该术语基本上会消失,留下:

$h + ($m2 - $m1) % 60 / 60

现在考虑如何计算$h:它是($m2 - $m1)除以60的商,删除余数(因为int())。另一方面,($m2 - $m1) % 60 恰好是该分区的剩余部分。因此,上面的表达式基本上只是将从$h中删除的余数部分添加回来。因此它与

具有相同的结果
($m2 - $m1) / 60

答案 1 :(得分:6)

您可以使用Time::Piece进行简单的日期/时间计算:

#!/usr/bin/perl

use strict;
use warnings;

use Time::Piece;

my $pattern = '%H:%M';

my $start = Time::Piece->strptime('09:00', $pattern);
my $end   = Time::Piece->strptime('16:45', $pattern);

my $diff  = $end - $start;
print $diff->hours;

输出:

7.75

请注意,$diff实际上是Time::Seconds个对象。

答案 2 :(得分:1)

我会说使用Time::Piece,但我认为这是某种练习。

在Unix中,所有日期都会转换为自纪元以来的秒数。当一切都在同一单元中时,它可以很容易地对事物进行算术运算。因此,我会将时间转换为分钟,执行操作,然后将时间转换回小时和分钟。这意味着你需要子程序。一个将时间从小时和分钟转换为分钟。一个将分钟转换为小时和分钟。

#! /usr/bin/env perl
#
use warnings;
use strict;
use feature qw(say);

my $time1 = "9:50";
my $time2 = "16:45";

my $time1_in_minutes = convert_to_minutes( $time1 );
my $time2_in_minutes = convert_to_minutes( $time2 );

my $diff_in_minutes = $time2_in_minutes - $time1_in_minutes;

say convert_to_hours( $diff_in_minutes );


sub convert_to_minutes {
    my $time             = shift;

    my ($hours, $minutes) = split /:/, $time;
    my $total_minutes = ( $hours * 60 ) + $minutes;
    return $total_minutes;
}

sub convert_to_hours {
    my $minutes         = shift;

    my $hours = int $minutes / 60;
    $minutes = $minutes % 60;
    return sprintf "%d:%02d", $hours, $minutes;
}

通过将工作分解为两个子程序,您可以轻松查看正在发生的事情。另外,你有更多的灵活性。如果我给你时间跑马拉松,我想要平均时间怎么办?您可以使用相同的两个例程。如果我给你每天在工作上花的时间怎么样,我想要总计?同样,您可以使用相同的子例程。

并且,因为更容易看到正在发生的事情,所以更容易纠正编程时出现的错误。更好的是,因为操作干净,我可以开始添加功能。例如,检查我的输入会很好。在我的convert_to_minutes子例程中,我可能希望确保小时和分钟有效。中间有一个冒号。分钟不超过60分钟。