답변:
Perl에 round () 함수가 있습니까? ceil ()과 floor ()는 어떻습니까? 삼각 함수?을
int()
향해 잘립니다0
. 특정 자릿수로 반올림sprintf()
하거나printf()
보통 가장 쉬운 경로입니다.
printf("%.3f", 3.1415926535); # prints 3.142
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).재무 응용 프로그램의 반올림은 심각한 영향을 줄 수 있으며 사용 된 반올림 방법을 정확하게 지정해야합니다. 이 경우 아마도 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을 비난하지 마십시오. IEEE와 마찬가지로 C도 마찬가지다. 절대 값이
2**31
(32 비트 시스템에서) 정수인 펄 숫자는 수학 정수와 매우 유사하게 작동합니다. 다른 번호는 보장되지 않습니다.
printf
변수에 결과를 원한다면 사용하지 마십시오. sprintf
이것은 디버깅 시간을 절약하기를 바랍니다
int()
PDL에 사용할 수 있습니까 ?
보다 일반적인 (사소한) 유스 케이스의 경우 중간 표시 등에 대한 복잡한 답변에 동의하지 않는 경우 :
my $rounded = int($float + 0.5);
최신 정보
$float
음수가 될 수 있으면 다음과 같은 변형으로 올바른 결과를 얻을 수 있습니다.
my $rounded = int($float + $float/abs($float*2 || 1));
이 계산으로 -1.4는 -1로 반올림되고 -1.6은 -2로 반올림되며 0은 폭발하지 않습니다.
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
모듈 (표준 펄 분포의 일부)을 구현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을 비난하지 마십시오. IEEE와 마찬가지로 C도 마찬가지다. 절대 값이 2 ** 31 (32 비트 시스템) 미만의 정수인 Perl 숫자는 수학 정수와 매우 유사하게 작동합니다. 다른 번호는 보장되지 않습니다.
외부 모듈이 필요하지 않습니다.
$x[0] = 1.2;
$x[1] = 1.7;
foreach (@x){
print $_.' = '.( ( ($_-int($_))<0.5) ? int($_) : int($_)+1 );
print "\n";
}
나는 당신의 요점을 놓칠 수도 있지만, 이것이 같은 일을하는 것이 훨씬 깔끔한 방법이라고 생각했습니다.
이것이하는 일은 요소의 모든 양수를 살펴보고 언급 한 형식으로 숫자와 반올림 된 정수를 인쇄하는 것입니다. 이 코드는 소수를 기준으로 한 반올림 된 양의 정수를 연결합니다. int ($ _)는 기본적으로 숫자를 내림 하므로 ($ -int ($ ))는 소수를 캡처합니다. 소수가 (정의 적으로) 엄격하게 0.5보다 작 으면 숫자를 내림하십시오. 그렇지 않은 경우 1을 추가하여 반올림하십시오.
다음은 값을 요약하는 5 가지 방법의 샘플입니다. 첫 번째는 합산을 수행하고 실패하는 순진한 방법입니다. 두 번째는을 사용하려고 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
당신이 소수를 필요로 할 때, 그 때의 ( 디스플레이가 ky니다).
정확하고 수학에는 별다른 문제가 없지만, 디스플레이에서는 "-0.0"과 같은 것이 이상하게 보입니다.
int 메소드의 경우 음수는 결과로 원하는 것을 변경할 수 있습니다 (올바르게 만들 수있는 인수가 있지만).
은 int + 0.5
당신이 그런 식으로 일을하지 않으려면, 제외 어 번호와 실제 문제가 발생하지만 대부분의 사람들이하지 않는 상상한다. -0.9는 0이 아닌 -1로 반올림해야합니다. 음수가 바닥이 아니라 천장이되기를 원한다면 1- 라이너로 수행 할 수 있습니다. 수정 (이것은 분명히 정수를 되 찾는 것입니다.
my $var = -9.1;
my $tmpRounded = int( abs($var) + 0.5));
my $finalRounded = $var >= 0 ? 0 + $tmpRounded : 0 - $tmpRounded;
전체 부동 소수점 숫자 (예 : 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);
}
if ($digit3 >= 5) { $digit3 = 0; $digit2++; if ($digit2 > 9) { $digit2 = 0; $digit1++; if ($digit1 > 9) { $digit1 = 0; $cost[0]++; } } }
그러면 다음과 같습니다. if ($digit1 >= 5) { $digit1 = 0; $cost[0]++; }
return commafied($cost[0]);