C++相談室 part156

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
垢版 |
2021/05/19(水) 10:55:13.24ID:LZZifCH2
前スレ
C++相談室 part155
https://mevius.5ch.net/test/read.cgi/tech/1616555235/
2021/07/04(日) 14:15:48.87ID:WJcubPcO
>>640
いやすまん2は確かに間違いでauto hoge = func()はhogeへのmoveで済む

>>639
いやすまん「〜できる場合だけ」という限定は間違いやった

ついでに言うとbar(func())でたまたまfunc()がスタック上に作ったreturn valueのアドレスも変えずにそのままbar()に渡せるとき
moveが起きるという主張も間違いだったかも……(アドレスも変わらないのなら何の構築も不要
2021/07/04(日) 14:27:18.68ID:bouvqZmG
何もかもおかしいよお前
「コピー返し」って結局なんやねん
独特の語法でわけのわからんことを主張するな
「印象」「かもしれない」で物事を主張するな
何がわかってて何がわかってないか知れ
質問と主張をごちゃまぜにするな
本格的に社会に居場所なくなるぞ

「全部取り下げます」とだけ言って去れ
で一から勉強しろ
643デフォルトの名無しさん
垢版 |
2021/07/04(日) 14:32:24.17ID:2p3tbjy0
RPGでアイテムを移動させた時に間違ってコピーされてアイテムが増殖する
ムーブしないといけない
アイテムは一個だけ
2021/07/04(日) 14:37:46.88ID:HHbHqtlq
>>642
面倒見よくて草
昔はこの板にもアンタみたいな厳しい先輩いっぱい居たのにな
今はニワカと趣味グラマが何周送れかわからんポエム呟きあってるだけだし
昔からいる人らは完全スルーしてるはず
2021/07/04(日) 14:52:36.20ID:WJcubPcO
>>642
Callerが(スタック上に)確保したメモリに対してcalleeが構造体を返すという返し方の意味
これについては統一した用語が無いようなのでむしろ知りたいっすね……

>>643
>>623のコードでSにムーブコンが定義されていなかったら増殖を意図しないケースでも
コピコンが呼ばれるのだから>>643はたとえとしてはイマイチ
2021/07/04(日) 15:12:00.11ID:7/Zaj2J4
>>645
要件を満たすとき (返却値が prvalue のとき) は変数の場所に直接にオブジェクトが構築される.。
コピーやムーブを省略できるというのはそういう意味で、
特に C++17 以降ではコピー省略が許されるときにはコピーコンストラクタもムーブコンストラクタも存在しなくてもいい。

https://wandbox.org/permlink/FOndP8P7Ecv5v5sB
2021/07/04(日) 15:50:43.27ID:WJcubPcO
>>646のコードをVS2019でビルドしたら
>error C2280: 'foo::foo(foo &&)': 削除された関数を参照しようとしています
と言われるorz

ていうか「prvalueならば必ず変数の場所に直接にオブジェクトが構築される」(例外なくそうなる)のだとしたら
これはcallerがcalleeに構築すべき変数のアドレスを渡さねば実現できない芸当だけど
ABIにそんな隠れた第n引数を設けることまでC++の規格で決めちゃって委員会、
とそこはかとなく疑問が……
(funcがメンバ変数だった場合、隠れた第1引数でthisを渡すことになっているのにこれにさらに追加?
2021/07/04(日) 15:56:31.25ID:xLbwwiyt
いいからお前はRVOでぐぐって来い
話はそれからだ
2021/07/04(日) 16:02:57.96ID:WJcubPcO
>>648
これか
https://blog.kmc.gr.jp/entry/2014/12/20/231430
>まるでメンバ関数における暗黙のthisポインタのように、関数の引数に戻り値を格納する先の変数へのアドレスを渡します。
>そしてそのアドレスの先の上にオブジェクトを構築することで、関数内部での一時オブジェクト
>生成を呼び出し元のオブジェクト生成とみなすことができます。 このようにしてRVOは実現されています。

>まるでメンバ関数における暗黙のthisポインタのように、関数の引数に戻り値を格納する先の変数へのアドレスを渡します。
mjk、
2021/07/04(日) 16:18:10.24ID:2qJME2iB
>>649
RVO は、最適化の一種なので、実現方法は色々。
とにかく、コンパイラが、関数の戻り値から左辺へのコピーやムーブを
なるべく減らして、いきなりダイレクトに左辺に書き込むような方法を探し出して
コード化する。
それをどやってやるかは、関数呼び出しの ABI 依存。
2021/07/04(日) 16:52:18.97ID:VOtERW9V
>>647
エラーになるのは、VS2019のデフォルトがC++14だから。
プロジェクトのプロパティ→構成プロパティ→C/C++→言語 の
「C++言語標準」を「ISO C++17標準(/std:c++17)」に変更すれば通る。
2021/07/04(日) 18:28:13.63ID:WJcubPcO
>>651
確かに「C++言語標準」を「ISO C++17標準(/std:c++17)」に変更したら通った

>>651
>(RVOを)どやってやるかは、関数呼び出しの ABI 依存。
そういうものだと今の今まで思っていたが、
C++17で>>646のコード(コピコンもムーブコンも明示的に削除)がビルドが通るようになるということは、
第2の隠れた引数でcallerがcalleeに構築すべき変数のアドレスを渡すことが
C++17では義務化されるとしか解釈できないのでは……
2021/07/04(日) 20:21:13.81ID:WJcubPcO
第2の隠れた引数でcallerがcalleeに構築すべき変数のアドレスを渡しているのだとすると
>>627のコードが"default"の次に"copy"になるのはある程度説明がつく
 1. return_S()関数でS構築 --- ここでS:S()が呼ばれ、"default"表示
 2. auto hoge = return_S()では何も起きない(∵1で&hogeにSが構築済み)
 3. take_S(hoge)で呼び出しの引数としてhogeをコピー
   --- &hogeにあるSが、スタックの上の方に引数としてコピーされる結果"copy"表示

しかしhogeはその後使っていないのだから、コンパイラ的には3はmoveになる余地があるはず

なお>>641までの漏れのレスは第2の隠れた引数は仮定せず、return_S()(callee)がスタックのトップに
return valueとしてS()を構築して、
それが呼び出し元(caller)が&hogeにcopy(ムーブコンがあればmove)する穏当なモデルを考えていた
実際n3337.pdf(古いが)を読む限りRVOのやり方は全く規定されてないからアリのはず……
何で>>642が怒り狂うのかわからん……
2021/07/04(日) 22:02:15.33ID:dMFRzHLQ
>>652
別に実装として「隠れた引数」を使えとは規格上決まっていないよ
処理系は適当な専用のグローバル変数を使うようなコードを出力しても構わない

>>653
なんで>>642が怒り狂うのか?
>>642を読んで分からない分からない?
あなたの一連のレスはあなた自身以外の誰のためにもなっていないんだよね
>>642でするな、って言われていることは、そういう自分のためにしかならないことでスレを私物化する行為に等しいよってことだ
2021/07/05(月) 08:27:16.47ID:4kBMhQOc
>>653
>>603は調べたんかいな。cpprefjp な。
RVOを含めて調べれば、>>646だということは分かるだろ。
c++標準の扱いはcpprefjpの参照リンクにもある「値のコピー省略の保証について」が良くまとまっている。

検索・調査能力が低いのは今どきのプログラマーとして致命的欠陥だから、日頃から訓練したほうがいい。
2021/07/05(月) 08:31:59.73ID:4kBMhQOc
補足。
>>653の2はNRVOだからRVOとは別物な。
NRVOは最適化可能だけどコピー省略は保証されていない。
2021/07/05(月) 08:44:01.31ID:4kBMhQOc
>>656
あ、間違えた。NRVOとは関係ないや。

ついでに。
>しかしhogeはその後使っていないのだから、コンパイラ的には3はmoveになる余地があるはず

副作用のあるコピーコンストラクタがあったら最適化はやばいんじゃない?
規格上許されていたっけ?
2021/07/05(月) 11:05:56.38ID:w3Zb0u1p
ライフタイムを推論してcopy/moveの振り分けは理論上可能かもしれないが、現行の規格はそんなことは要求しない
lvalueからならcopy、rvalueからならmove
lvalueからmoveしてほしいならstd::moveしなさい
lvalueを渡しているのに勝手にrvalue referenceとして解釈されてぶっ壊されてたまるかよ
2021/07/05(月) 12:24:14.81ID:M+MHtMKE
template<class T>
class A {
public:
A()=default;
A(T&&);
};
この場合、T==Aになるとmoveとcopyを兼ねる?
2021/07/05(月) 13:59:53.08ID:MxHqaq3M
C++が出来るとは規格書がちゃんと読めることを言うんだね
2021/07/05(月) 15:27:44.85ID:NDiogwds
Macのclang++でコンパイルしています。
cstdlibをインクルードしなくてもrand()が使えてしまうのですが、これはなぜでしょうか?
2021/07/05(月) 15:36:50.05ID:M+MHtMKE
規格票には規格書なんて書いてない
俺はちゃんと読めるんだなんて
イキッてるやつはブーメランだな
2021/07/06(火) 00:27:03.56ID:86XKd96p
>>657
許されてるよ
その状況でコピコンやムーコンが呼ばれるかどうかは未規定(呼んでも呼ばなくてもいい)
というかこの「呼ばなくてもいい」っていう規定こそが正に規格がNRVOを認めてる部分そのもの
2021/07/06(火) 03:32:03.53ID:PiE4/OQH
実際、「move さえ省略してほしい」って思惑で
auto hoge = func();
と書くところを
auto&& hoge = func();
と書いてる人なんているの?
2021/07/06(火) 07:29:15.81ID:6WiwYssU
いるよ。
2021/07/06(火) 07:45:25.63ID:FcxtUR1g
>>657
エピステーメーも同じようなこと言ってたけどね
まぁコピーコンストラクタとかにコピー以外の副作用入れる方が悪い、ってことだろ
実際変な副作用など無いことを前提にしなきゃ出来ない最適化他にもあるやろ
2021/07/06(火) 10:03:46.67ID:t2+Z62DR
>>661
stdlib.hにも定義されているが、他のヘッダをincludeすると、
その中から別のヘッダをincludeしている場合も有り、その中からさらに
別のヘッダをincludeしている場合も有る。
また、標準ではstdlib.hやcstdlibで定義されているとされていても、
その他のヘッダで定義されていないとも限らない。
2021/07/06(火) 20:25:19.80ID:/lKUoH39
>>666
>コピーコンストラクタとかにコピー以外の副作用入れる方が悪い
規格票のどこに?
2021/07/06(火) 23:17:37.91ID:2d1Iatqp
>>668
規格票持ってるんですか?
2021/07/07(水) 00:20:29.64ID:ACi5C/C8
>>668
コイツたまにトリップ外すの忘れて荒らしみたいなことしてんの最高に滑稽
2021/07/07(水) 05:18:00.78ID:BiM5c4gH
>>668
副作用がある場合でも省略されるというのは明記されている。

https://timsong-cpp.github.io/cppwp/n3337/class.copy#31
> even if the copy/move constructor and/or destructor for the object have side effects
2021/07/10(土) 14:04:49.30ID:yQTcABkI
>>658
3がmoveになったところで何も壊れるものは無くね?
というのと、take_S()に渡される方がぶっ壊されることにはならないので
3がmoveになってもlvalueとして渡されることには変わりは無い
2021/07/11(日) 00:07:46.98ID:5nx6GB9W
>>672
https://cpplover.blogspot.com/2009/11/rvalue-reference_23.html
とりあえずこれとか読んでからお願いします
全体的に何が言いたいかよく分からないですがmoveならrvalueとして渡されるのでそこは理解してください
2021/07/11(日) 00:24:04.38ID:YJk6tGcw
>全体的に何が言いたいかよく分からないですが
ヒエッ……このスレは荒れる……
2021/07/11(日) 00:27:13.08ID:YJk6tGcw
>moveならrvalueとして渡されるのでそこは理解してください
rvalueになるのは移動の右辺であり3のケースでは(3がmoveになったとして)移動元のhogeの実体だが
take_S()に渡るのはmoveされた後のhogeなのでtake_S()の中では問題無くlvalue扱い
2021/07/11(日) 00:28:49.03ID:YJk6tGcw
しつれい、
誤: take_S()に渡るのはmoveされた後のhoge
正: take_S()に渡るのは&hogeからmoveされてきたhogeの「複製」
2021/07/11(日) 00:51:20.33ID:5nx6GB9W
リンク先読んだ?
2021/07/11(日) 00:53:43.57ID:YJk6tGcw
もとから読んでるっつーの;;;
>>677はムーブコンストラクタで構築されたオブジェクトがlvalueでないと思っちゃうタイプ?
2021/07/11(日) 00:54:17.11ID:5nx6GB9W
3.でmoveは発生しません
詳細はさっきのブログ記事に書いてあります
以上
2021/07/11(日) 00:55:29.24ID:YJk6tGcw
>>679
どこか指摘できずに逃亡;;;
2021/07/11(日) 00:57:15.79ID:5nx6GB9W
lvalueをmoveせよ

さて、2. はどうしたらいいだろう。moveコンストラクタを実装したものの、コンパイラは2. の場合には、moveコンストラクタを呼び出してくれない。なぜなら、コンパイラは、プログラマの脳内仕様を読んではくれないからだ。tmpが、その後に使われていないかどうかは、コンパイラは静的に決定できないのである。

そこで、プログラマが意図を伝えてやらなければならない。

X b( static_cast<X &&>(tmp) ) ;

この様に、rvalueにキャストしてやれば、moveコンストラクタを呼び出すことが出来る。
2021/07/11(日) 01:01:18.54ID:YJk6tGcw
>>679はSのインスタンスhogeを関数void take_S(S) (※void take_S(S&)ではない!)に渡す際に、
take_S()の呼び出し元(この場合main())が
hogeと同じ値を持つインスタンスをtake_S()の引数用領域に構築する必要がある、というあたりからして理解していないのではないか;;;
で、問題にしているコードはリンク先の
>tmpが、その後に使われていないかどうかは、コンパイラは静的に決定できないのである。
には該当しない
2021/07/11(日) 01:04:39.70ID:YJk6tGcw
なぜなら、今回のケースはコードを見たらワカルからじゃわ;;;
コンパイラは静的に決定できない、と言っているのは停止性問題を解く万能のアルゴリズムが無いことから来ているが、
特殊なケースでは停止性問題は機械的に解ける
今こそその時、

、というあたりからして>>679はちんぷんかんぷんなのではないか……
2021/07/11(日) 01:11:23.21ID:5nx6GB9W
あーそこがわかってなかったのね
take_Sの仮引数を実引数で初期化する時に同じことが起こるだけですよ?
実引数をrvalue参照とみなしてオーバーロード解決できればmoveで仮引数が初期化される
できなければ(かつlvalue参照として解決できれば)copyで仮引数が初期化される
2021/07/11(日) 01:24:29.28ID:YJk6tGcw
>>684
藻前の頭が固いだけなんとちゃうか;;;

>実引数をrvalue参照とみなしてオーバーロード解決できればmoveで仮引数が初期化される
この場合(すなわち実引数hogeをtake_S()の仮引数としてコピーした後呼び出し元が実引数hoge()を使わない(ことをコンパイラが機械的に判定できる)ケース)
において、実引数hogeのアドレスをrvalue参照とみなしてはいけないという根拠は?
論理的にはソースコードの意味を変えることなく整合するんだけどそういう最適化はいけないことなの?
2021/07/11(日) 02:58:15.91ID:YJk6tGcw
んまーとは言ったものの、
【実験1】 >>627のコードをループにしてやって最適化「-O2」にしても"move"にならなんだorz
https://wandbox.org/permlink/2kwbZ4cxyfMDe9VC
結果:
default
--------
copy
0, 1
default
--------
copy
1, 2
...

※ ループにした他、コピコンとムーブコンをそれぞれ「それらしく」実装もしてゐる、
2021/07/11(日) 02:59:10.66ID:YJk6tGcw
【実験2】 もちろんstd::move(hoge)したらmoveになる
(上記リンク先のコードのDO_MOVE定義のコメントアウトを外してを有効化)
結果:
default
--------
move
0, 1
default
--------
move
1, 2
...

【実験3】 また、中間変数hogeを使わずtake_S(return_S())するとcopyもmoveも起きない
(上記リンク先のコードのUSE_ITM_VARの定義をコメントアウトして無効化)
結果:
default
0, 1
default
1, 2
...
2021/07/11(日) 03:09:25.47ID:YJk6tGcw
(言い訳1)
実験3のような最適化が許されるのだから、copyをmoveに読み替える最適化も許されるべきだ
規格に照らしてどうなのかはC++規格の専門家の反応待ち

(言い訳2)
今回のケースでGCC様がcopyをmoveにする最適化を拒むのは、単にhogeの使用箇所の分析をサボっているか
(データフロー解析の一環として論理的には十分take_S()呼び出し後の未使用を機械的判定をやれるはずなのに…
、デストラクタのdefault[] のコストでも気にしている可能性が微レ存

(言い訳3)
>>627のコードでmoveになる、と最初に言い出したのは>>609であって漏れではない
むしろ漏れは「場合によってはcopyが起きる」(>>623)と述べてたのでcopy派である
(C++17のRVOが要請するABIについて誤解していた感じなのでであんま大きな声では言えないが
2021/07/11(日) 13:04:35.11ID:G2C/uXds
>>685
> 論理的にはソースコードの意味を変えることなく整合するんだけどそういう最適化はいけないことなの?

コピーコンストラクタとムーブコンストラクタのどっちが呼ばれたかわかるようにログ出力とかしてたら動作が変わる。
そういう副作用を含めてコンパイラが動作を変えていいケースは >>671 で挙げられたように明示的に規定されていて、
あなたの言うケースはそうではない。
2021/07/11(日) 18:47:32.64ID:8K44AFaV
>>688
Copy になるべき場合と Move になるべき場合は条件がはっきりしている。
どちらでもいい場合は無い。

表層上の動作が仕様通りであればどうコンパイルしても良いのが C/C++ なので、
あえて、あくまでもあえてレアケースを挙げるとすれば
(見かけ上の) 動作が Copy でも Move でも同じだとコンパイラが見ぬくことが出来る場合が
あったなら Copy の場面で Move 相当の機械語が生成されることが絶対にないとは言いきれないけども、
Copy でも Move でも同じだと確信できる場合に限られるので動作からはどうせ観測できない。

意味を変える最適化をしていいという唯一のルールがコピー (またはムーブ) の省略で、
その一部が C++17 では必須化されたわけだね。
2021/07/12(月) 07:46:00.62ID:5HFqt1x5
ある整数がある整数の n 乗であることの判定ってどうするのが良いでしょうか
(n も整数とします)

今までは
x == (int)pow((int)pow(x, 1.0/n), n)
で判定してたんですが、今の自分の環境で x = 4096、n = 6 を渡したら誤判定しました

(int) を round に変えるのを思いつきましたが、コーナーケースがあったら嫌なので、他の良い方法があったら教えてください
2021/07/12(月) 08:17:32.01ID:K0Wntvol
>>691
諦めてboostの多倍長整数を使う。
2021/07/12(月) 08:25:49.14ID:Vv9VoiuP
>>691
double y = pow(x,1.0/n);
int iy = (int)y;
iy==y
このほうが多少マシにはなると思うが根本的な解決になってないので
double epsilon = 0.00000001;
y-iy < epsilon;
にするとか
2021/07/12(月) 09:45:03.47ID:Q0n0f8DA
>>691
どこまで高速化したいのかわからんけど頑張ってn乗計算するとか
https://qiita.com/b1ueskydragon/items/0b8e0c382d782423c6d3
2021/07/12(月) 10:01:12.57ID:5HFqt1x5
>>692
多倍長整数でどうやるんでしょうか?


>>693
確かに、改めて n 乗する意味なかったですね


>>694
後出しですみませんが、遅くて良いから短くて誤判定のないのが望ましいです
2021/07/12(月) 10:11:36.07ID:5HFqt1x5
>>693
y の小数部分が 0.9999999998 とかだと失敗しますよね?
iy = round(y) として abs(y - iy) < 1e-12 で判定しようかなと思います
2021/07/12(月) 10:22:44.45ID:D0qCNAQT
>>690
最後だけ認識おかしい、唯一ではない
2021/07/12(月) 12:24:08.89ID:uJpO0uZ2
>>697 他に何かあるなら教えて。
2021/07/12(月) 12:35:12.60ID:4jaglyfV
>>695
boost 多倍長整数 冪乗 で検索。
書くのは色々と面倒だから、解説ページ読め。boost はpowも対応している。
2021/07/12(月) 17:41:28.01ID:D0qCNAQT
>>698
わかりやすいとこで言えばStrict Aliasing Rulesとか
型が違おうが何だろうが、本来一度書いたものが、次別のポインタ(or参照)を読む時同じ場所だったら、さっき書いた値になってなければならない
・・・んだが、そんなこと守ってたら最適化なんかほとんど出来ないだろ
他にC++の仕様に規定されてなくとも各コンパイラは色々やってる
大抵は問題ないが、ごくまれに意図した挙動になってくれなくて困ることはあるぞ
2021/07/12(月) 18:26:33.31ID:3yd7dMb1
>>691
>>692
アホな文系の質問にアホな文系が答えるスレ?

どの値が与えられて、その値の条件(範囲、符号、...)は何か
環境は仮定していいのか、(C++の規格範囲内の)すべての環境で正しく動作する必要があるのか
コードに求めるものは何か?(可読性、速度、...)
をはじめからすべて書きなさい
2021/07/12(月) 18:32:42.82ID:3yd7dMb1
ごく一般的なPC環境で、与えられた整数がintの範囲であれば、
(ある程度の判別を行ったあと)普通に四捨五入で良い

n乗根の候補を求めたあと整数領域でn乗してもいいし
元の数を(割り切れる判別をしながら)候補で割っていってもいいし
与えられた整数が32bitの範囲であれば、2分検索やリニア検索してもいい

アホな文系が理解できる範囲で自分の頭で考えて自分の責任でコードを書きなさい
2021/07/12(月) 19:47:47.34ID:F4g5ptiT
>>701
そういった諸々の細かい調整を諦めて多倍長整数を使う、ということだよ。
そもそもの要件(n乗判定)でpowを使う乱暴さを考慮すれば、面倒な部分を処理してくれるライブラリを使用するのは有力な選択肢。それを無視して「アホな文系」とは言ってくれる。

ご高説を宣ってくれた後にどんな素晴らしい解説を>>702でしてくれるのかと思ったら、n乗判定にわざわざ割り算を持ち込んだり、対数にも触れずに検索にフッ飛ぶ滅裂ぶり。>>601が混乱するのを笑うために書き込んでいるとしか思えん。

文系、文系と馬鹿にする人間は、人間と会話のできない発達障害が多いのかね?
2021/07/12(月) 20:05:16.58ID:3yd7dMb1
ヒント
多倍長整数を使っても何も解決しない
2021/07/12(月) 20:29:50.05ID:4jaglyfV
>>704
なんで解決しないのか解説してもらいたいねぇ。
2021/07/12(月) 20:34:24.53ID:rFlF3L7g
累乗根は浮動小数点の演算だからだよ
2021/07/12(月) 20:52:49.79ID:xS7m7lUb
いや累乗して整数同士で比較すりゃええやん
2021/07/12(月) 21:00:52.19ID:+DCDGa5F
n乗数判定は明らかに整数論の問題なんですがそれは

なお一番簡単な平方数判定でもNPなんで(一発でポンと答えが出る楽な方法は多分)ないです
709デフォルトの名無しさん
垢版 |
2021/07/12(月) 21:13:08.21ID:q3a62lD+
因数分解してハッシュで数えて全部6の倍数なら何かの6乗なんじゃないの


4096=2^12

h{2}→12個

12は6の倍数なので何かの6乗


3*7*3*7*3*7*3*7*3*7*3*7 = 85766121 だと

h{3}→6個
h{7}→6個

両方6だから何かの6乗
2021/07/12(月) 21:14:32.03ID:M5TNNHP+
累乗根の演算で引数の逆数をどうやって整数で表現するの?
>>691の例で言えば、n=6なら6乗根(=1/6乗)の計算を行なっている
2021/07/12(月) 21:21:35.61ID:uJpO0uZ2
>>700
未定義動作となる場合はそもそも「意味」が定まらないので「意味を変える最適化」とかいう話にならないよ。
712デフォルトの名無しさん
垢版 |
2021/07/12(月) 22:14:22.14ID:vW8lyXRJ
ひさしぶりにみると
すごく
カオスなスレッド
2021/07/12(月) 22:33:30.20ID:j4Yh95VG
>>709
>>702 が言ってるのがそれじゃ無い?
> 元の数を(割り切れる判別をしながら)候補で割っていってもいいし
2で割り切れなくなるまで割り、割った回数がnの倍数で無ければNG
3で割り切れなくなるまで割り、割った回数がnの倍数で無ければNG
を繰り返すって事かと(多分)
2021/07/12(月) 22:51:10.50ID:MoTlox7M
数値計算としては>>693,696がもっとも正統派の方法だよ
素直に累乗根を求めて誤差を評価して判定する
わざわざトリッキーな手段を採る必要性は無い
2021/07/12(月) 23:38:51.54ID:PjBVtdER
>710
「 累乗の判定」と「 累乗根の演算」をごっちゃにしている?

「累乗根の演算」はあくまで「 累乗の判定」の候補となる整数を
見つける手段の一つで、必ずしも必要ではない。
極端な話、候補となる整数を2から順番に数えて判定しても良い。
まあ、「できるだけコードを簡単に」という話なら素直に累乗根を
使ったほうが良いけど、その時でも(累乗/累乗根計算の誤差の問題から)
「 累乗の判定」を行う必要がある。

>693 >714
よくよく>691を見たら、本質的にはintによる切り捨ての問題だな。
0.5を足して実質的に四捨五入になるようにすりゃいい。

>691の計算を下敷きにするなら
int y = pow(x, 1.0/n)+0.5;//<-これ重要
int z = pow(y, n)+0.5;//<-これも重要だと思う
として、
x == z
を判定すりゃいいんじゃね? 試してないけど。
2021/07/12(月) 23:48:10.49ID:3yd7dMb1
長々と書いてやっと質問者と同レベルに追いついた
アホな回答者

全部>>702に書いてるし
2021/07/12(月) 23:51:52.50ID:3yd7dMb1
ある整数やnがマイナスの場合に言及してるのは>>701だけ
質問者も他の回答者もそこまで頭がまわらない
2021/07/12(月) 23:57:47.66ID:xS7m7lUb
そっかあ
あたまがいいんだね
2021/07/13(火) 00:17:32.29ID:u8F7J+OY
>>699
いや、
整数 x、y、n が与えられたときに x が y の n 乗であるかどうか判定する
ではなく、
整数 x、n が与えられたときに x が y の n 乗となるような整数 y があるかどうか判定する
ですよ?

多倍長整数なんて出る幕ないでしょう
もしかして y を全ての自然数について全探索するのを想定してる?
高卒?
2021/07/13(火) 00:31:12.29ID:u8F7J+OY
>>701
質問者自身が int にキャストとか round とか言ってるんだからどう見ても自然数の話でしょ
バカ


>>702
> n乗根の候補を求めたあと整数領域でn乗してもいいし
> 元の数を(割り切れる判別をしながら)候補で割っていってもいいし
なんで今更質問者(>>696)より筋の悪い方法を提案するの?笑

> 与えられた整数が32bitの範囲であれば、2分検索やリニア検索してもいい
これしきの問題で何を探索することがあるんだよバァ〜〜〜カ
つーかわざわざ二分探索とかするならそれこそ桁数めっちゃ多いときの方が有効だろ
なぜ32bitに限った?
2021/07/13(火) 00:34:18.46ID:u8F7J+OY
>>707
えっっっっ
やっぱり根を探索するつもりだったんだ
ヤベーなお前
2021/07/13(火) 00:38:55.05ID:u8F7J+OY
>>708
何と勘違いしてんのか知らんが、ここで与えられてる問題は桁数 n に対して明らかに O(n) で解けるだろ
アホ
2021/07/13(火) 00:45:05.26ID:u8F7J+OY
>>715
質問者より数歩後ろを歩いてるのにすごく堂々としていてかっこいいです
2021/07/13(火) 00:54:56.07ID:lAJ4enjR
構ってほしいなら昨日のID教えてよ
2021/07/13(火) 01:00:26.91ID:2F1zpnof
ウーン、質問者!w
2021/07/13(火) 01:00:52.89ID:MEdkoaBM
>>711
アホだろお前
2021/07/13(火) 01:02:39.35ID:+UxqO86S
そうでもないよ。
2021/07/13(火) 01:28:13.49ID:bx8BDdOP
>716
あれ? もしかして>702?
>702は回答としてもヒントとしても全然駄目じゃない?

>695の問題の本質はstd::powの誤差の発生の仕方(プラスマイナス両方出る)と
double -> int キャスト時の誤差切り捨て(0に近づく方に切り捨て)の
ミスマッチなのに、>702ではそんなこと何も言及していないよね。

もしこれで「書いている」と感じるようなら、もっと人間に説明する方法を
勉強したほうが良いと思うよ。
729728
垢版 |
2021/07/13(火) 01:31:47.96ID:bx8BDdOP
自己フォロー
>695の問題の本質はstd::powの誤差の発生の仕方
1.0/nでも誤差発生しているか。std::powとどっちの誤差がデカイかね?
2021/07/13(火) 01:38:26.00ID:2F1zpnof
もしかしてっつーかモロID一緒じゃん
あとみんな分かってることを周回遅れで「本質」として宣言すんなって
あと安価間違いし過ぎ

ホント迷惑だからもうやめとけ
2021/07/13(火) 01:39:24.44ID:u8F7J+OY
boost多倍長整数クン顔真っ赤でワロ
2021/07/13(火) 02:08:48.23ID:FVC0BsAk
この中のどれがQZがコテ外して書き込みしているのか想像したら(*´艸`*)
2021/07/13(火) 02:10:33.69ID:RS3RIqhF
>>668
これとか完全に荒らしのやり口だもんな
2021/07/13(火) 02:30:29.04ID:bx8BDdOP
>730
誤差の発生の仕方と誤差切り捨てのミスマッチが問題ということが分かっているなら、
なんで>691への回答でそれを指摘しないの?
この話で重要な「切り捨て」という単語すらスレで3回しか出てきてないし。
それにdoubleに0.5足して/引いてからintにキャストとかCで誤差を扱うときの
定石だろうに、0.5bニいう数字自体bルとんど出てこbネい。

結局>691に助言したいんじゃなくてマウントしたいだけだから当然か。
分かってて余計な説明しかしないんだから、なんとまぁ不親切なやつなんだろうかね。

さて、書きたいこと書いたので風呂入って寝るかね。
2021/07/13(火) 02:42:44.22ID:2F1zpnof
>>734
round という語が出た回数とその場所も調べたまえ
指摘するまでもなく質問者は>>691,696にして早々それに気付いている
2021/07/13(火) 03:09:56.56ID:itar1i0e
そもそも>>696の処理であれば切り捨て誤差は発生しない
round() と abs() の2段構えで対策はされてるよ
0.5 を加算するよりずっとスマートな記述だな
2021/07/13(火) 03:11:08.93ID:itar1i0e
被った
すまん
2021/07/13(火) 07:55:39.92ID:Fq8PEpca
>>728
四捨五入ってわかるかな?
質問者が分かってることがわかるからそれだけ書けば十分
分かってないのはお前だけ

>>720
小数の誤差を見積もれない、見積もるのが面倒
というなら整数領域だけで答えを導く方法もある
頭の悪い文系にはそういう発想は出てこないかな?

intも整数もマイナスの数を含むんだよね定義的には
範囲を確認するのは当然
質問者も含め勝手な思い込みはバグの元
2021/07/13(火) 09:33:54.05ID:53YTa3I7
Pow(x, n) ... n乗
Pow(x, 1.0/n) ... n乗根
Pow(x, -n) ... n乗の逆数
Pow(x, -1.0/n) ... n乗根の逆数
740デフォルトの名無しさん
垢版 |
2021/07/13(火) 12:07:43.02ID:WUJYnH4r
>>712
どんなときでも共通するのは声が大きい香具師が勝つ
その場の空気を支配した香具師が勝つ
そしてマスゴミによって印象操作された世界の完成
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況