質問
使用する配列(c)を比較するためのofactoメソッドです memcmp
から string.h
?
ユニットテストでINTとダブルの配列を比較したい
次のようなものを使用するかどうかわからない:
double a[] = {1.0, 2.0, 3.0};
double b[] = {1.0, 2.0, 3.0};
size_t n = 3;
if (! memcmp(a, b, n * sizeof(double)))
/* arrays equal */
またはオーダーメイドを書く is_array_equal(a, b, n)
タイプ関数?
解決
memcmp
します ちょうど 比較は、フロートにとってめったに良い考えではなく、nan!= nanというルールに従うことはありません。並べ替えについては、それは問題ありませんが、他の目的のために、次のようなおおよその比較を行うことができます。
bool dbl_array_eq(double const *x, double const *y, size_t n, double eps)
{
for (size_t i=0; i<n; i++)
if (fabs(x[i] - y[i]) > eps)
return false;
return true;
}
他のヒント
交換 memset
と memcmp
あなたのコードでは、それは機能します。
あなたの場合(サイズの両方の配列アレイは同一であり、コンパイル中に既知です)。
memcmp(a, b, sizeof(a));
使用 memcmp
一般的には良い考えではありません。より複雑なものから始めて、そこから作業しましょう。
あなたは言及しましたが int
と double
, 、最初に集中したいです memcmp
タイプの配列を比較するなどの一般的なソリューションとして:
struct {
char c;
// 1
int i;
// 2
}
主な問題は、実装が場所1と2の構造にパディングを自由に追加できることであり、重要なビットが完全に一致しているにもかかわらず、潜在的に誤った比較を行うことです。
ダブルスになりました。パディングがないので、これはより良かったと思うかもしれません。ただし、他にも問題があります。
1つ目は治療です NaN
値。 IEEE754は、それを確実にするために邪魔になりません NaN
それ自体を含む他の値と等しくありません。たとえば、コード:
#include <stdio.h>
#include <string.h>
int main (void) {
double d1 = 0.0 / 0.0, d2 = d1;
if (d1 == d2)
puts ("Okay");
else
puts ("Bad");
if (memcmp (&d1, &d2, sizeof(double)) == 0)
puts ("Okay");
else puts
("Bad");
return 0;
}
出力されます
Bad
Okay
違いを示す。
2つ目は、プラスとマイナスゼロの処理です。これらは比較の目的で平等と見なされるべきですが、ビットパターンが異なるため、 memcmp
それらが違うと言うでしょう。
の宣言/初期化の変更 d1
と d2
上記のコードで:
double d1 = 0.0, d2 = -d1;
これを明確にします。
したがって、構造とダブルが問題になっている場合、確かに整数は大丈夫です。結局のところ、彼らは常に2人の補完です、はい?
いいえ、実際にはそうではありません。 ISOは、署名された整数の3つのエンコーディングスキームのいずれかを義務付けており、他の2つ(1つの補完と署名/大きさ)は、プラスとマイナスゼロの両方が存在するという事実と同様の問題に苦しんでいます。
したがって、それらはおそらく平等と見なされるべきですが、再びビットパターンは異なります。
のためでさえ 署名なし 整数には問題があります(署名された値の問題でもあります)。 ISOは、これらの表現には価値ビットとパディングビットがあり、パディングビットの値は不特定であると述べています。
だから、最も単純なケースのように見えるかもしれないことでさえ、 memcmp
悪い考えかもしれません。
あなたが探している機能はです memcmp
, いいえ memset
. 。の答えを参照してください この質問 なぜそれが良い考えではないかもしれない理由のために memcmp
ただし、ダブルスの配列。
MEMCMPは、与えられたサイズ数について2つのメモリブロックを比較します
memsetは、与えられたサイズの値でバッファーを初期化するために使用されます
バッファーは、MEMCMPを次の方法で使用せずに比較できます。異なるデータタイプでも同じことが変更できます。
int8_t array_1[] = { 1, 2, 3, 4 }
int8_t array_2[] = { 1, 2, 3, 4 }
uint8_t i;
uint8_t compare_result = 1;
for (i = 0; i < (sizeof(array_1)/sizeof(int8_t); i++)
{
if (array_1[i] != array_2[i])
{
compare_result = 0;
break;
}
}