2012-04-05 23 views
3

は、以下の条件で私を助けてくれますか? 私は$ priceと$ lsecを比較しようとしています。 。文字列を浮動小数点に変換する

if((sprintf("%.2f", ($price*100+0.5)/100)*1 != $lsec*1)) 
{ 
       print Dumper($price,$lsec) 
} 

(文字列など)時には、ダンパ版画同じ番号とにジャンプ 思想、1と乗算することは、彼らから山車を作ること...

ここでダンパー出力:

$VAR1 = '8.5'; 
$VAR2 = '8.5'; 

私は間違って何をしていますか?

ありがとう、

挨拶とハッピーイースター。

+1

丸めが発生すると予想される場合、 '$ price * 100 + 0.5'はおそらくあなたが期待したことをしません。 '$ price = 8.5'では方程式の一部が' 850.5 'になります。 – TLP

+1

'perl -e 'printf"%.2f "、8.505''を実行して、間違っていることを確認してください。 – mob

+0

あなたは '$ price'と' $ lsec'をダンプしていますが、それはあなたが比較している数字ではありません。 –

答えて

3

あなたは1で、文字列を乗算すると、それを強制することを言うことが正しいです:これは、この警告を集めるだろう==で、数値以外の文字列を比較しようとしているので、もう一つの理由に、あなたのPerlスクリプトで常にuse warningsです数値として評価されるが、数字の!=は同じことをするだろう。これはおそらく、Perlが一般的に正しいことを実行するので、他の言語から取得したテクニックであり、いずれかのオペランドのキャストを強制する必要はありません。

use strict; 
use warnings; 

use Data::Dumper; 

my $price = '8.5'; 
my $lsec = '8.5'; 

my $rounded_price = sprintf("%.2f", ($price * 100 + 0.5)/100); 
print "$rounded_price <=> $lsec\n"; 

if ($rounded_price != $lsec) { 
    print Dumper($price,$lsec); 
} 

出力

8.51 <=> 8.5 
$VAR1 = '8.5'; 
$VAR2 = '8.5'; 

ので、Perlが正しく8.51が8.5に等しくないことを言っている:

あなたが比較している値を見てみましょう。

は、私はあなたの

($price * 100 + 0.5)/100 

$price 2に小数点以下を四捨五入することを意図していると思われるが、それは実際にはない、すべては0.005で$priceを高めることです。私はあなたが

int($price * 100 + 0.5)/100 

を書くためのものだと思いますが、あなたはまた同じことを行うための別の方法であるsprintfを通じて価値を置きます。

どちらか

$price = int($price * 100 + 0.5)/100 

または

$price = sprintf ".2f", $price 

が、両方は過剰です!

+0

コンディションの中に複雑なコードがあると、何が起こっているのかを知ることが難しいです。 Borodinの答えの最も重要な部分は、問題を明らかにするクリーンなコードです。 –

-3

あなたは何も間違っていません。 Perlはそれをダンプする前に文字列に変換します。比較のために、数値比較には==!=、文字列比較にはeqneを使用します。 Perlは必要に応じて文字列と数値に変換します。

例:

$ perl -MData::Dumper -e "my $a=3.1415; print Dumper($a);"

$VAR1 = '3.1415';

+0

あなたは問題を説明していません - 8.5が明らかに8.5と違うことがわかりました。 – Borodin

+0

間違った部分は、限られた精度を使った浮動小数点演算がしばしばあいまいであることを認識していません。 –

1

この部分:

($price*100+0.5)/100) 

あなたが8.5に入れた場合、あなたが戻って8.505を取得します。自然に8.5に等しくない。 $priceを変更しないので、違いは気付きません。

Perlは自動的に変換を処理しますので、心配する必要はありません。

my $x = "8.5"; 
my $y = 8.5; 
print "Equal" if $x == $y; # Succeeds 

比較の性質上、==またはあなたのケースで!=は、彼らが数値であるかどうか、数値に引数を変換します。

3

は、Perl変数にが格納され、それがどのようにが使用されているかの違いがあります。あなたは、1を掛けることによって、変数がになり、を数値に強制することが正しいです。また、数字は、インタプリタへの変数を表すSVデータ構造体に格納されます。あなたはPerlが各変数に格納しているものを見るためにDevel::Peekモジュールを使用することができます。

use Devel::Peek; 
my $num = "8.5"; 
Dump $num; 

出力:継続

SV = PV(0xa0a46d8) at 0xa0c3f08 
    REFCNT = 1 
    FLAGS = (POK,pPOK) 
    PV = 0xa0be8c8 "8.5"\0 
    CUR = 3 
    LEN = 4 

...

my $newnum = $num * 1; 
Dump $num; 
Dump $newnum; 

出力:我々はと懸念している

SV = PVNV(0xa0a46d8) at 0xa0c3f08 
    REFCNT = 1 
    FLAGS = (PADMY,NOK,POK,pIOK,pNOK,pPOK) 
    IV = 8 
    NV = 8.5 
    PV = 0xa0be8c8 "8.5"\0 
    CUR = 3 
    LEN = 4 
SV = NV(0x9523660) at 0x950df20 
    REFCNT = 1 
    FLAGS = (PADMY,NOK,pNOK) 
    NV = 8.5 
PV

属性(文字列ポインタ)、NV(浮動小数点数)、及びIV(整数)です。最初は$numには文字列値しかありませんが、数値として使用すると(たとえば乗算で)、数値が格納されます。しかし、$numはまだそれが文字列であることを "覚えている"ので、Data::Dumperはそのように扱います。

ほとんどの目的のために、は明示的にの演算子と関数が最も適切な形式でそれらを使用できるので、文字列の使用を強制します。たとえば、==!=演算子は、そのオペランドを数値形式に変換して数値比較を行います。代わりにeqまたはneを使用すると、文字列の比較が強制されます。

Argument "asdf" isn't numeric in numeric eq (==) at -e line 1. 
+1

これをBorodinの答えに加えれば、あなたはかなり全体の話を持ちます。 :) –

+0

私はData :: Dumperが文字列として値を格納しているが、それに対して算術演算をさせる例がある。もしJSON :: PPがすべてを引用することを嫌っていたら、私は大丈夫でしょう。では、スカラーの記憶を強制的に数値にする方法はありますか? * 1と+1はまだ私のために働いていません。 – ericslaw

関連する問題