C++相談室 part158

■ このスレッドは過去ログ倉庫に格納されています
2021/11/15(月) 18:49:18.44ID:I69rZ/Of
前スレ
C++相談室 part157
https://mevius.5ch.net/test/read.cgi/tech/1628474251/
510デフォルトの名無しさん
垢版 |
2021/12/23(木) 21:54:27.28ID:4lOSoN0i
メモリ確保用途でvectorやstringつかい
ポインタアクセスすれば、new で確保するのと速度に大差ないとおもうんですが
実測すると10%〜くらいSTLつかうほうが速度低下するみたいなんですが
直メモリアクセスでも落ちるのはなぜなんでしょうか
2021/12/23(木) 22:14:02.53ID:6YhOrdG1
その計測コード貼ってみ
多分メモリアクセスとは関係ない所で時間食ってる
2021/12/23(木) 22:16:19.47ID:lsirm1I0
>>509
ありがとうございます
やはりクラスを利用しないと実現無理そうなので、498のようなC#で言うところのstatic class的な形でやることにします
513510
垢版 |
2021/12/23(木) 22:21:06.77ID:4lOSoN0i
これです・・・


https://ideone.com/NKSCRi


vector : 974.971 ms
new char : 921.191 ms
new int32 : 899.579 ms
514デフォルトの名無しさん
垢版 |
2021/12/23(木) 22:38:03.27ID:MjSWMWRR
1秒もかかる?
515510
垢版 |
2021/12/23(木) 22:49:58.53ID:4lOSoN0i
こっちだと大差がついてるんですが
家のPCでもideone.comよりも差が付きます vector確保のほうが遅い


https://paiza.io/projects/9wWo36-bjTCL_S0WcGbaWA

vector : 459.154 ms
new char : 184.758 ms
new int32 : 167.899 ms
516510
垢版 |
2021/12/23(木) 22:55:16.12ID:4lOSoN0i
自己解決しました
メモリ確保と解放部分を含めて計測してたのを
コピー部分のみの測定にしたらほぼ一緒になりました


https://paiza.io/projects/ge5iOWrzGu2E2PjogsRlUw

vector : 219.947 ms
new char : 204.565 ms
new int32 : 214.644 ms
2021/12/23(木) 22:55:24.77ID:6YhOrdG1
ほとんどメルセンヌツイスタの実行時間じゃね
518デフォルトの名無しさん
垢版 |
2021/12/23(木) 22:56:40.08ID:MjSWMWRR
確保にかかってると思う?
一秒はさすがにないと思う。
何かおかしいな。
519デフォルトの名無しさん
垢版 |
2021/12/23(木) 22:58:15.18ID:MjSWMWRR
vector云々以前に、newバージョンも遅すぎると思う。
話にならないくらい。
i8008とかじゃないよね?
2021/12/23(木) 23:00:56.66ID:6GqfEn2+
C++/CLIでstd::mutex使えないのなんでなん?

頑張ってWin32APIで代用する気力はあるけどわざわざ無効化されてる理由が知りたい
521510
垢版 |
2021/12/23(木) 23:05:52.89ID:4lOSoN0i
メモリ確保・解放と、メルセンヌツイスタを外して計測したら
今度はvectorのほうが圧倒的に早いんですが

https://ideone.com/rKv4qv

vector : 237.55 ms
new int32 : 713.82 ms
2021/12/23(木) 23:26:56.25ID:4lOSoN0i
計測時間は、ある程度の長さで、オンライン実行環境のタイムアウトにならないように
ループ回数を変更してるので
2021/12/23(木) 23:54:08.59ID:58w1xOUi
生ポインタにしたら同じ感じにならない?
unique_ptr<int32_t[]> p(new int32_t[2*size]);
int32_t* A = p.get();
mmcpy(A, size);
2021/12/24(金) 01:54:49.07ID:T9e6TA98
手動でループ回数変更とか馬鹿らしいからquick-bench.comとか使うのオススメ
2021/12/24(金) 09:00:08.27ID:opQHMY4K
overrunがある
std::make_uniqueを使え
2021/12/24(金) 09:04:03.38ID:opQHMY4K
https://ideone.com/JupGoY
527デフォルトの名無しさん
垢版 |
2021/12/24(金) 09:05:00.82ID:6d0f054m
サンプルコードだからと安易にnew演算子使う風潮やめたほうがいい
コールバックや別スレッドに渡すインスタンスの生成にのみnew演算子を使うべき
2021/12/24(金) 09:08:39.52ID:opQHMY4K
そういうことではなくunique_ptrを理解してから使えというだけ
2021/12/24(金) 09:09:02.65ID:6d0f054m
バッドノウハウがいつまでたってもなくならない原因は入門者向けのサンプルコード
2021/12/24(金) 09:09:36.51ID:opQHMY4K
そもそもサンプルコードの質が悪すぎる
2021/12/24(金) 09:10:57.45ID:opQHMY4K
今回のね(>>526)
2021/12/24(金) 09:11:48.94ID:6d0f054m
>>528
むしろ「理解してなくても使え」だよ
ナマポだってそうだ
サティアンとか金目とかじゃなくてな
実際に使って痛い目にあわないと
2021/12/24(金) 09:12:11.50ID:opQHMY4K
>>462は壮大な勘違い
2021/12/24(金) 09:13:48.09ID:opQHMY4K
>>532
何でもそうだが、理解しないで使うからこういう問題が跡を絶たない
「理解してなくても使え」が何よりも悪い
2021/12/24(金) 09:21:12.05ID:6d0f054m
>>534
それは違う
使わなければ理解できないよ
自身が初心者だった頃を思い出せないくらい耄碌したの?
お大事に
2021/12/24(金) 09:22:45.08ID:opQHMY4K
>>535
俺は初心者の頃から理解できていないものを何となく使うとかはしていない
それが何よりも悪いことを教わってきてるから
2021/12/24(金) 09:25:48.61ID:ZnDQBfvC
練習と本番を一緒くたにしてるな
まさに現場の癌だったと自白してるようなものだ
2021/12/24(金) 09:28:20.47ID:opQHMY4K
まさにお前がな
2021/12/24(金) 09:30:24.34ID:opQHMY4K
コロコロID変わる質問者兼劣悪回答者の荒らしで、そもそも勤務経験なさそう、と思ってるよ
2021/12/24(金) 09:31:16.13ID:6d0f054m
>>536
現役離れてずいぶん経つの?
実務やってれば仕様書の文章があいまいで実際に動かさないと理解できないってことがいくらでもあるでしょ
「仕様書はない、ソースのみ(キリッ」という状況なんて普通なはずだが
2021/12/24(金) 09:32:13.38ID:6d0f054m
教わるとか受け身かよ、アホかと
学ぶんだろ
2021/12/24(金) 09:35:00.51ID:6d0f054m
上司が「お前は触るな」と言いたいのをオブラートに包んで「理解してから触れ」と言われたクチだろう
できないPGだった証拠
543デフォルトの名無しさん
垢版 |
2021/12/24(金) 09:36:56.46ID:6d0f054m
「理解してから使え」なんて、危なっかしい無能な人を開発現場から穏便に排除する時に使う言葉だよ
544デフォルトの名無しさん
垢版 |
2021/12/24(金) 09:42:48.15ID:6d0f054m
肩叩きされていたことに気づけないくらいに読解力が低い
2021/12/24(金) 09:48:44.26ID:ZnDQBfvC
「理解してから使え」
「はい、理解してきます」
「理解しました!今度こそ大丈夫です」←わかった気になってるが自分が何を分かっていないのかがわからない
546デフォルトの名無しさん
垢版 |
2021/12/24(金) 09:54:19.02ID:6d0f054m
普通は他人に迷惑かけることなく作業しろ、って言えば良いいんだけど、
察するに上司はそれまでの積み重ねで追放する気満々だったんじゃないかな
547デフォルトの名無しさん
垢版 |
2021/12/24(金) 10:05:26.45ID:6d0f054m
unique_ptrやshared_ptrは初心者でもコンパイラのエラーや警告に従うだけで安全にコードを書けるようになるからおススメだと思うよ
もちろん頓珍漢な警告メッセージを出力する不親切なコンパイラだとそうはいかないが
2021/12/24(金) 12:58:00.18ID:a16a8gMY
下らない煽りを何回にも分けて書くな無能
2021/12/25(土) 15:17:39.58ID:miWR5HNI
コールバックや別スレッドに渡すインスタンスの生成であっても
new演算子を使わねばならない必然性は無いので

ていうかnewしたブツを渡した先でdeteteさせる設計のは
newしたコードとdeleteするコードが同じCRTでないと危険なので
異なるプロジェクトの間でやるのは一般にアンチパターンなので
 1. そもそも渡さない(利用するスレッドに生成させる
 2. (どうしても渡したい場合は)コピーして渡す
 3. オブジェクトの所有権を渡す側のスレッドが握って生存期間が利用期間を包含することを保証する
のどれかなので
2021/12/25(土) 15:18:01.17ID:miWR5HNI
少なくともウィンドーズのDLLはDllMain()を有する1本のプログラム同然なので
Ver.0.1のCRTをスタティックリンクしたDLLというものが作れてしまうので
Ver.0.2のCRTとリンクされるコードで生成したオブジェクトのポインタを渡せてしまうので
2021/12/25(土) 15:49:34.78ID:/YMztZoD
のでので言ってるだけで結論がない
頭悪そう
2021/12/25(土) 21:39:56.11ID:0AIK3bm0
ActiveX系使ったことないんだろうなって容易に推測でける
2021/12/25(土) 23:47:20.34ID:miWR5HNI
しらそん
COMオブジェクトの中で異なるバージョンのCRTの混在が起きたら
同じことなんじゃないの
554デフォルトの名無しさん
垢版 |
2021/12/26(日) 01:42:46.74ID:Fmrpdwj0
アウトプロセス
2021/12/26(日) 02:08:50.44ID:rFpP4pcL
しらそん
アウトプロセスサーバが生成する
COMオブジェクトの中で異なるバージョンのCRTの混在が起きたら
同じことなんじゃないの
なので
2021/12/26(日) 02:10:54.75ID:P9feSsDc
自演って見苦しいな
2021/12/26(日) 05:25:00.76ID:0FjCQ3kx
>>549
そういうのをスマポでやれって話?
ヘッダで提供されるライブラリだからスマポもダメだと思うんだけど
2021/12/26(日) 05:43:12.94ID:a8PAglQ+
>>552
急にCOM持ち出すのはおかしいだろ

>>553
ふつーCoTaskMemAllocじゃねえかな
2021/12/26(日) 07:28:31.98ID:z66Mwoku
sin関数に入れる時間変数の値が大きくなるにつれ誤差が増えていって困ってます
fmod関数を使ってもあまり効果が見られませんでした
処理時間をそれほどかけずに解決出来る良い案何かありますか?

sin関数に入れる値の目安は100万くらいです
2021/12/26(日) 09:18:24.17ID:6eMF2SNy
100万をsin()しても、sin()は2π周期
doubleの精度15桁中の5桁以上を無駄にしている

sin()する用変数で毎回fmod(,2π)してもそこで誤差が貯まりそう

boost::multiprecisionとか?
2021/12/26(日) 09:35:40.45ID:/woV9P1D
出来るなら入れる数を作る時点で[0,2pi)に収まるように工夫する
それが無理なら多倍長浮動小数点数のライブラリ使うか自作するか
2021/12/26(日) 10:28:27.14ID:a8PAglQ+
>>559
sinの引数に入れる値を浮動小数点数で少しずつ足しこむような処理をしているなら、やめて別の方法を考えろ
2021/12/26(日) 11:32:37.05ID:SV9DgXqP
sinに時間を入れるのは次元がおかしい

っていうのは冗談で、質問者が何を問うてるのかわからん
sinにdoubleに収まるどんなデカい数を入れても精度は15桁くらい保証されるでしょ


>>560
> 100万をsin()しても、sin()は2π周期
> doubleの精度15桁中の5桁以上を無駄にしている
これもわけわかんねー
100万近いある数 x をsin()に入れるんでしょ?
x も sin(x) も上から15桁全部有効な桁でしょ
何が無駄になってるん?


>>562
こういう話ならわかる
2021/12/26(日) 12:03:23.64ID:/woV9P1D
sinのテイラー展開にxの大きな累乗が現れるからだよ
100万をバンバン累乗した級数で値域[-1,1]の関数計算してたら誤差まみれになるのは直感的に分かるだろ
2021/12/26(日) 12:47:17.91ID:6eMF2SNy
>>563
318310 * pi が100万に近い2piの倍数
https://keisan.casio.jp/calculator で、14桁で計算する

2 * pi = 6.2831853071796
sin(6.2831853071796) = 1.3523E-14

318310 * pi = 1000000.3575642
sin(1000000.3575642) = 3.291426496E-8

わかった?
桁数同じだから、でかい数は細かい所が消えるのよ
566デフォルトの名無しさん
垢版 |
2021/12/26(日) 15:05:31.07ID:N3NYq5+A
わかんない。
2021/12/26(日) 15:55:33.50ID:SV9DgXqP
>>565
現象としては確認できたが、理屈が分からない
>>564の言ってるようにテイラー展開の各項が激しくキャンセルし合って桁落ちするってこと?
2021/12/26(日) 16:03:55.94ID:6s7ujcJo
>>564
のテイラー展開は疑問なんだけど
関数が[0,pi/2.)への押し込みもやってくれるんじゃないの
2021/12/26(日) 17:28:50.32ID:6eMF2SNy
「桁数同じだから、でかい数は細かい所が消える」が理屈のつもりなんだけど…
sin(6.2831853) = -7.179586477E-9 だし、
sin(1000000.3575641670857) = -3.5E-14 だよ
2021/12/26(日) 17:52:52.66ID:6eMF2SNy
sin()の結果に13桁の精度が欲しいなら、入力値に小数点以下13桁の精度が要るのよ
sin()は2piの周期関数だから
1000000の所に7桁も使っちゃうのはもったいないのよ
2021/12/26(日) 19:17:02.92ID:P9feSsDc
まだ小学校の算数で分かる誤差の話してんの?
>>560で話終わらん奴は小学校からやり直せよ
2021/12/26(日) 19:41:54.46ID:qnixUQRF
桁に関する誤差とかどこの世界の小学校で習うんだよ
2021/12/26(日) 22:29:03.39ID:Ep2AbKxF
お前は小学校の国語からやり直せw

>> まだ「小学校の算数で分かる」誤差の話してんの?
誰も小学校で習うなんて言ってないぞ
2021/12/26(日) 22:43:40.78ID:RjefXsAR
log1pの存在理由も似たような話だね
2021/12/26(日) 23:16:02.57ID:P9feSsDc
俺小学4年生で級数展開したπの計算してたけど・・・
6年生でアセンブラと実数使ってたけど・・・
2021/12/27(月) 08:46:39.54ID:B/I2o19O
教える奴もよく分かってないからめちゃくちゃになってる

基本的には大きい数についても>>563の考え「x も sin(x) も上から15桁全部有効な桁」で合ってる
sin() が 0 になるケースを考えてるからややこしいんだよ
sin() が 1 になるケース、つまり pi/2 の奇数倍で 100 万に近い数を入れてみろ
そしたらちゃんと 15 桁くらい 1 になるから

0 がややこしい理由は、仮数部が何であっても良いから
例えば 1e-20 は仮数部には1桁目からゴミが入っているが、倍精度ではゼロと見なす
2021/12/27(月) 10:35:52.12ID:wn+BpFxZ
>>576
お前は>>560様の爪の垢を煎じて飲んでから、小学校をやり直せ
2021/12/27(月) 18:35:09.36ID:osgcVgi4
uniform_real_distribution の範囲を可変にしたいときってどうしたら良いでしょうか
0 から 1 までの実数を生成するようにしてそれを変数変換するべきですか
2021/12/27(月) 19:02:31.64ID:DQqD3vMw
っparam
2021/12/27(月) 20:26:27.31ID:7ufKNB24
>>576
1になるケースでほぼ1になるのは、そこでの微分が0だからだよ
入力値がちょっとずれても結果への影響が小さいのよ
2021/12/27(月) 20:45:16.64ID:7ufKNB24
「x も上から15桁全部有効な桁」だからこそ、
1000000の所に7桁も使っちゃうのはもったいないのよ

sin(x)=0の所は微分が1または-1、入力のずれがそのまま出力に出る所
2021/12/28(火) 01:04:16.62ID:OVEU2JJm
厳密な2πnと、doubleで表した有効桁数15桁の大体2πnに近い数字の差を計算すると、nが大きくなるほど差がデカくなってくるってだけの話じゃないの?
浮動小数点数は0から離れれば離れるほど目盛りが大きくなっていくのだから。
sinの実装がマクローリン級数展開でなくても起こる問題だと思うが。
2021/12/28(火) 01:43:08.31ID:NIM0c1vY
小学生多すぎじゃないか?
2021/12/28(火) 09:17:10.46ID:p+qHklGW
おまえさん1人だろ
中学以後、いつ何を習うか知らないようだが
2021/12/29(水) 21:49:37.03ID:+eZ32Uo6
>1e-20 は仮数部には1桁目からゴミが入っているが、倍精度ではゼロと見なす
mjk、

IEEE754の2進数形式の倍精度浮動小数点表示は
仮数部がケチ表現の52 bit(実質53 bit)で
指数部は-1022〜+1023なのやぞ
1e-20とか1×2^(-60)かそこらなので無問題で53 bit(=15.9桁)の精度ェ、
2021/12/29(水) 21:55:43.45ID:+eZ32Uo6
>sin(x)=0の所は微分が1または-1、入力のずれがそのまま出力に出る所
x << 1のとき
sin(x) ≒ x
であることの見事な工学的応用、
2021/12/29(水) 21:57:34.77ID:+eZ32Uo6
まつがえた |x| << 1 やったorz
2021/12/30(木) 01:48:03.91ID:L6Vpkxay
よっしゃ、よっしゃ、おっちゃんがいいもん作ったろう
https://ideone.com/fjxKtS

n=0,10000, 20000, 30000, ...,1000000 (とりあえず10000刻み)として、
2分探索でsin(x)=0となるxを、2π*n付近について調べてやった

そうやって求めたxをM_PIで割った結果はきっちり2*nになるから
sin(x)がxの周期関数だからといって必ずしもxの増大につれ誤差が増えるわけではないことがワカル

sin_valの値(=sin(x))が0に対して増えたり減ったりするのはマクローリン展開の近似多項式の係数を
結果があたりさわりのない誤差範囲でうろうろするように調整してあるんだろJK、
2021/12/30(木) 01:51:27.40ID:L6Vpkxay
やっぱ>>562というものが>>559の誤差の真相なのではな
いか
2021/12/30(木) 02:32:05.49ID:7UdZ08Kf
>>588
結果見たけど、sin_valの値は、きっちり0から10000になったときに5桁精度悪化してるし、100000で6桁精度悪化してるのでは…?
2021/12/30(木) 07:31:31.40ID:xtSEOuqd
>>589
パッと見だけど>>565が答えじゃねえの
浮動小数点てのは文字通り小数点位置が異なる
数値が1付近と100万付近じゃ精度が異なるのは当たり前
精度を保つなら固定小数点使わないと
2021/12/30(木) 11:37:53.79ID:ZhVAaRAF
まだやってたのか小学生・・・ID変えてご苦労様
2021/12/30(木) 11:39:17.39ID:ZhVAaRAF
何度も言ってるが>>560でこの話は終了している
2021/12/30(木) 12:38:33.70ID:A3EHubzP
質問主が現れないからもう何議論しても無駄な気がする
ソースコードがあるわけでもないし

100万程度で誤差ヤバい言うぐらいだからfloatで計算してないか疑たくもなる
2021/12/30(木) 14:43:33.58ID:Wt/MKF34
誰も計算機上のゼロについて理解できてない
2021/12/30(木) 16:49:59.36ID:uaiyfMI5
もまいら、浮動小数点のゼロ判定どうしてる?
2021/12/31(金) 00:22:01.38ID:kcosmPcn
vectorでクラスへのポインタを持ってて、それを参照で受け取る関数を作るとき、クラスの変更を禁止したいんですが、どうすればいいですか?

例えば、
struct testclass{
int member;
};
というクラスがあって、
vector<testclass*>
を参照渡しで受け取る関数を作るとき、引数をconst vector<testclass*>& vecとしてもvec[0]->member =0みたいなクラスのメンバ変数の変更は関数の中で出来てしまうと思うのですが、そういうのをできないようにしたいです(testclassの変更が無いことを関数宣言で保証したいです)
何か良い方法ありますか?

vectorが1重であればtestclass const*const*を引数にすればいいとは思うのですが、vector<vector<testclass*>>のように多重vectorみたいな場合も作りたくて、そのときは関数を呼ぶ側で多重vectorから多重配列に変換するのは面倒なので、できればvectorではなく配列を使うというのはしたくないです
2021/12/31(金) 00:36:47.69ID:ysmsTKqS
>>597
禁止しない
もしくはメンバ変数を非publicにしてgetter/setter
2021/12/31(金) 05:02:18.38ID:zF3P5q1E
だから絶対値が1e-14とかより小さいかどうかだって

>>585なんかは全く理解してないようだが
2021/12/31(金) 05:10:34.66ID:zF3P5q1E
ちなみにsinがゼロのとこは微分が1か-1でsinが1のとこは微分がゼロだから違うってのは、事実だが今回の事象の説明としては感覚的に過ぎるね

なぜならf(x) = xなる関数は微分は1だが f(1000000.3575642) は14桁正しいw

sinの挙動について理解したいなら実装に踏み込むしかないよ
あるいは>>576あたりで思考停止しとくか
2021/12/31(金) 06:37:46.15ID:qJZ2APUI
>>597
アクセスを厳密に禁止したいなら、配列操作のみ定義したラッパークラスを用意して渡したほうが良い。
2021/12/31(金) 08:06:29.68ID:FnYy2lty
んだね
2021/12/31(金) 08:45:47.76ID:FPee+d5o
クラス T のメンバ関数で自身のコピーを返す(つまり返り値の型が T)ものを考える
メンバ関数の修飾が && のときは std::move(*this) とかしたいけどこれはいちいち書かないとダメ?
普通は std::forward で統一できるが
2021/12/31(金) 09:05:22.16ID:FnYy2lty
*thisはxvalueではないからムブコンに渡したければstd::move()か(T&&)がいるね
2021/12/31(金) 11:52:30.35ID:kcosmPcn
>>598
ありがとうございます
ただ、
>メンバ変数を非publicにしてgetter/setter
これだと結局setterでメンバ変数を変更できてしまいますよね?

>>601
ありがとうございます、検討してみます
2021/12/31(金) 14:47:55.66ID:fEOKhR13
instance.field; が暗黙のうちに書き変わらないだけでも効果あるんだよ

void f(T&t){ t.clear();}
f(instance.field);
うっかりこんなことしたらヤバいし

const T& get_field() const;
を使っとけばコンパイル時エラーにしてくれる

>>597 冒頭の質問なら、参照渡し引数に
void f(const T&);
のようにconstつけとけばいい
2021/12/31(金) 15:16:00.18ID:7kXupeFa
>>597
まだ標準に入ってないけど、propagate_const使うとか
https://ideone.com/O8a0hn
608デフォルトの名無しさん
垢版 |
2022/01/04(火) 07:21:58.04ID:5hvio7Nh
Packtpubが不安定になってるんだけど。
見れますか?
2022/01/05(水) 21:49:37.99ID:2R8vvmqQ
クラステンプレートについて、明示的実体化しておけば実装を.cppでもできるというのを知ったのですが、その場合、テンプレートでない普通のクラスと同じように
部分的にヘッダに実装を書いて、残りを.cppに書く、というのは正式な書き方として許されるでしょうか?
2022/01/05(水) 22:24:10.67ID:tiBxT68+
許される。
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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