C言語関係掲示板

過去ログ

No.1208 閏年の判定(&& || の評価順)

[戻る] [ホームページ]
No.15870

分からない
投稿者---summer(2004/07/25 16:38:08)


条件:\称馭数が4で割り切れる年は「うるう年」、割り切れない年は   「平年」。
   ∪称馭数が4で割り切れる年のうち、100で割り切れて400    で割り切れない年は「平年」とする。
整数型の変数yearを宣言する。
”うるう年の判定プログラムです。”
”調べる年を西暦で入力して下さい。”を表示してyearに読み込む。
・もしうるう年なら
”○○○○年は、うるう年です。と表示
・もしうるう年でなかったら
”○○○○年は、平年です。”と表示する。

なんですけど、どうすればいいか分からないんです。


No.15871

Re:分からない
投稿者---ぽこ(2004/07/25 17:23:08)


>なんですけど、どうすればいいか分からないんです。

ご自分ではどこまでやられたのですか?
C言語をどこまで理解してますか?
今までの投稿文を見ると、課題の丸投げのような印象を受けます。
「全部が分からない」ではなく、疑問点の分割をやりましょう。

この程度のプログラムは20行程度で書ける筈なので、
ご自分でやられたところまでのソースコードを載せることをお勧めします。



No.15872

Re:分からない
投稿者---summer(2004/07/25 17:31:44)


>>なんですけど、どうすればいいか分からないんです。
>
>ご自分ではどこまでやられたのですか?
>C言語をどこまで理解してますか?
>今までの投稿文を見ると、課題の丸投げのような印象を受けます。
>「全部が分からない」ではなく、疑問点の分割をやりましょう。
>
>この程度のプログラムは20行程度で書ける筈なので、
>ご自分でやられたところまでのソースコードを載せることをお勧めします。

>どうやって、自分のやったのを載せるんですか?





No.15880

Re:分からない
投稿者---ぴかちゅう(2004/07/25 20:34:51)


#include <stdio.h>
#include <iostream>
void judgement(int y);
using namespace std;
main()
{
int year = 0;
puts("うるう年の判定プログラムです。");
puts("年を入力してね。");
scanf("%d", &year);
judegment(year);

}
void judgement(int y)
{
if(y % 400 == 0){
printf("%d年は、うるう年です。", y);

}
else if(y % 4 == 0 && y % 100 == 0 && y % 400!= 0){
printf("%d年は平年です。", y);
}


}
どうかなぁ?
自作関数を使ってもいいの?
環境を教えてください



No.15881

Re:分からない
投稿者---COCO(2004/07/25 21:52:28)


#include <stdio.h>

int main(void) 
{
    int year ;
    printf("うるう年の判定プログラムです\n") ;
    printf("調べる年を西暦で入力して下さい。\n") ;
    scanf("%d",&year) ;
    if (year % 4 == 0 && (! year % 100 == 0 || year % 400 == 0))
    {
        printf("%d年はうるう年です\n",year) ;
    }
    else
    {
        printf("%dは平年です\n",year) ;
    }
    return 0 ;
}

僕が作ったら、こんな感じになりました。
できるだけ、短くしたつもりです。
間違ってたら、すいません


No.15882

Re:分からない
投稿者---ニタチ(2004/07/26 12:43:44)


 if (year % 4 == 0 && (! year % 100 == 0 || year % 400 == 0)) は、
 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ですね。




No.15883

Re:分からない
投稿者---シャノン(2004/07/26 12:50:33)


> if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
if( year % 400 == 0 || ( year % 4 == 0 && year % 100 != 0 ) )
ちょっぴり高速化?



No.15884

Re:分からない
投稿者---シャノン(2004/07/26 12:53:24)


>> if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
>if( year % 400 == 0 || ( year % 4 == 0 && year % 100 != 0 ) )
>ちょっぴり高速化?

ごめん逆。
if( year % 400 == 0 || ( year % 100 != 0 && year % 4 == 0 ) )




No.15885

Re:分からない
投稿者---monkey(2004/07/26 13:23:23)


(1) if( year % 4 == 0 && ( year % 100 != 0 || year % 400 == 0 ) )
(2) if( year % 400 == 0 || ( year % 100 != 0 && year % 4 == 0 ) )

yearが一様乱数として与えられると仮定するならば,yearが4で割り切れない確率は75%,400で割り切れる確率は0.25%.
これらは,条件式の評価が,論理演算の第1項を評価した時点で終了する確率ですから,パフォーマンスは(1)の方が良さそうです.


No.15900

Re:分からない
投稿者---シャノン(2004/07/27 10:48:32)


>(1) if( year % 4 == 0 && ( year % 100 != 0 || year % 400 == 0 ) )
>(2) if( year % 400 == 0 || ( year % 100 != 0 && year % 4 == 0 ) )
>
>yearが一様乱数として与えられると仮定するならば,yearが4で割り切れない確率は75%,400で割り切れる確率は0.25%.
>これらは,条件式の評価が,論理演算の第1項を評価した時点で終了する確率ですから,パフォーマンスは(1)の方が良さそうです.

あちゃあ、恥ずかしい…
見なかったことにしといてやってください。



No.15901

評価について質問
投稿者---岡目八目(2004/07/27 10:51:46)


>(1) if( year % 4 == 0 && ( year % 100 != 0 || year % 400 == 0 ) )
>(2) if( year % 400 == 0 || ( year % 100 != 0 && year % 4 == 0 ) )
>
>yearが一様乱数として与えられると仮定するならば,yearが4で割り切れない確率は75%,400で割り切れる確率は0.25%.
>これらは,条件式の評価が,論理演算の第1項を評価した時点で終了する確率ですから,パフォーマンスは(1)の方が良さそうです.

コンパイラは、式の左からしか評価しなかったでしょうか?
カーニハンとリッチーの、C言語の本には、処理系に依存するとあったような気がするのですが.......
ANSIで、変わったのでしょうか?
教えてください。



No.15902

Re:評価について質問
投稿者---nop(2004/07/27 11:20:03)


>コンパイラは、式の左からしか評価しなかったでしょうか?
>カーニハンとリッチーの、C言語の本には、処理系に依存するとあったような気がするのですが.......

 「式1」&&「式2」

は、まず「式1」を評価し、評価結果が偽の時は「式2」の評価を行いません。
「||」についても同じで、「式1」が真の時は「式2」の評価を行いません。


また、オペランドの評価順も保証しているようです。(MSDN参照)

# 「,」演算子と一緒です。



No.15903

MSDNではそうですが、ISOでは規定がない。
投稿者---古い人(2004/07/27 12:01:45)


Microsoftのマニュアルには、自社の処理系の評価順序は記述していますが、C言語としては、処理系に依存すると言うことで、決まりがないようです。


No.15904

Re:MSDNではそうですが、ISOでは規定がない。
投稿者---nop(2004/07/27 12:10:23)


>Microsoftのマニュアルには、自社の処理系の評価順序は記述していますが、C言語としては、処理系に依存すると言うことで、決まりがないようです。

順序演算や「&&」、「||」は評価順序が仕様で決まっているようです。
C FQAとかわかりやすいかな?

# 順序演算子が評価順序不定なら、いまいち使い物にならないのでは?



No.15905

Re:MSDNではそうですが、ISOでは規定がない。
投稿者---Ban(2004/07/27 12:12:39)


>Microsoftのマニュアルには、自社の処理系の評価順序は記述していますが、C言語としては、処理系に依存すると言うことで、決まりがないようです。

IS 5.14 に、「左からの評価を保証する。右の評価はされないかも(意訳)」
という記載があると思いますが。


No.15906

Re:MSDNではそうですが、ISOでは規定がない。
投稿者---シャノン(2004/07/27 12:29:04)


>>Microsoftのマニュアルには、自社の処理系の評価順序は記述していますが、C言語としては、処理系に依存すると言うことで、決まりがないようです。
>
>IS 5.14 に、「左からの評価を保証する。右の評価はされないかも(意訳)」
>という記載があると思いますが。

蛇足。
C 言語では左から評価されますが、C++ ではこの限りではありません。
クラスが operator || をオーバーロードしていたりすると、両方評価されます。


No.15908

Re:MSDNではそうですが、ISOでは規定がない。
投稿者---Ban(2004/07/27 12:35:42)


>蛇足。
>C 言語では左から評価されますが、C++ ではこの限りではありません。
>クラスが operator || をオーバーロードしていたりすると、両方評価されます。

C++ でオーバーロードしてても、評価は左からを保証でいいんですよね?
右が評価されるかどうかは「されない'かも'」ですが。


No.15914

Re:MSDNではそうですが、ISOでは規定がない。
投稿者---YuO(2004/07/27 13:18:03)


>C++ でオーバーロードしてても、評価は左からを保証でいいんですよね?
>右が評価されるかどうかは「されない'かも'」ですが。

オーバーロードされた||演算子の両方のオペランドが常に評価されます。
また,どちらから評価されるかは未規定です。
#手元にISがないので,実装依存かもしれません。

つまり,
class foo { };
bool operator|| (const foo & lhs, const foo & rhs);
というようなとき,

foo a, b;
があって,
a || b

operator||(a, b)
として扱われますから,aとbは常に評価されます。


評価順序が決定しているのは,
・Cの場合か,C++で組み込みの演算子を利用している場合で
・&& || , の3種類の演算子に限る(左から右)
となります。ほかの演算子・場合においては,オペランドの評価順序は定まっていません。
また,関数呼び出し演算子を処理するより前に,引数やオペランドを評価することは決まっていますが,引数の評価順序は決まっていません。
つまり,引数の評価順序が左から右やその逆であることの保証は存在しません。



No.15919

Re:MSDNではそうですが、ISOでは規定がない。
投稿者---Ban(2004/07/27 15:10:34)


>operator||(a, b)
>として扱われますから,aとbは常に評価されます。

なるほど。
最終的に関数の引数に展開される以上、評価順は保証されない、と。
上の形で示されて納得しました。
# 関数の引数評価順は認識してたのに...>自分

危なく誤認してました。ありがとうございます。

# 'かも'の方は、認識自体は
# ・組み込みの演算なら常に評価されない。
# ・オーバロードしてあれば常に評価される。
# ->評価されるかどうかは場合による。
# だったものの、表現が不適切でちゃんと
# 説明できていませんでした。すみません。


No.15920

Re:MSDNではそうですが、ISOでは規定がない。
投稿者---シャノン(2004/07/27 15:55:26)


>つまり,
>class foo { };
>bool operator|| (const foo & lhs, const foo & rhs);
>というようなとき,

bool foo::operator ||( const foo &rhs );
のような時だと、

>foo a, b;
>があって,
>a || b
>は
>operator||(a, b)

a.operator ||( b )

なので、この場合は… a が先?
#何か勘違いしてる気がする。


No.15925

Re:MSDNではそうですが、ISOでは規定がない。
投稿者---Ban(2004/07/27 18:34:24)


>bool foo::operator ||( const foo &rhs );
>のような時だと、
>
>>foo a, b;
>>があって,
>>a || b
>>は
>>operator||(a, b)
>
>a.operator ||( b )
>
>なので、この場合は… a が先?
>#何か勘違いしてる気がする。

たしかに、そうなりそうな気がしますけど。
# a を評価して確定しないと、呼ぶべき operator が特定できない?

とりあえず「副作用のある式は極力混ぜない」という C 言語の格言(?)を
徹底していれば回避可能だと思いますが、なんか不定なのと大差ないような気も。



No.15940

Re:MSDNではそうですが、ISOでは規定がない。
投稿者---aki(2004/07/27 23:41:47)


>a.operator ||( b )
>
>なので、この場合は… a が先?
>#何か勘違いしてる気がする。

これは下のプログラムで関数fと関数gのどちらが先に呼ばれるかという問題
と同じです。どちらが先に呼ばれるかは未規定です。ドット演算子や関数呼
び出し演算子のオペランドの評価順序は未規定だからです。

#include <iostream>

struct X {
    void mf(int) {}
};

X f()
{
    std::cout << "f has called\n";
    return X();
}

int g()
{
    std::cout << "g has called\n";
    return 0;
}

int main()
{
    f().mf(g());    // すなわち (f().mf)(g());
    return 0;
}



No.15939

Re:MSDNではそうですが、ISOでは規定がない。
投稿者---aki(2004/07/27 23:27:06)


>評価順序が決定しているのは,
>・Cの場合か,C++で組み込みの演算子を利用している場合で
>・&& || , の3種類の演算子に限る(左から右)
>となります。ほかの演算子・場合においては,オペランドの評価順序は定まっていません。

条件演算子は?


No.15995

Re:MSDNではそうですが、ISOでは規定がない。
投稿者---aki(2004/07/29 18:02:08)


「間違いを書いておきながら、それを指摘されても訂正しないような人は
掲示板で回答者をやる資格はない」と、ひいおじちゃんが言ってました。

「そこまできびしい事言わなくてもいいんじゃないの?」と言い返しておい
てあげましたよ。


No.15907

Re:MSDNではそうですが、ISOでは規定がない。
投稿者---Ban(2004/07/27 12:30:00)


>コンパイラは、式の左からしか評価しなかったでしょうか?

これは以前の規格でも「関数など引数の評価」だったと思うのですが、
違いましたっけ?
# スタックの積順とか、コンパイラの実装に左右される...。
# 根拠が発見できなかったのですが、こっちは C++ の IS でも
# 保証されてないままなんでしょうか。



No.15996

Re:分からない
投稿者---COCO(2004/07/29 18:22:04)


>if (year % 4 == 0 && (! year % 100 == 0 || year % 400 == 0)) は、
> if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ですね。

あぁ。そうですね。
ご指摘ありがとうございました。