質問

使用する配列(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;
}

他のヒント

交換 memsetmemcmp あなたのコードでは、それは機能します。

あなたの場合(サイズの両方の配列アレイは同一であり、コンパイル中に既知です)。

memcmp(a, b, sizeof(a));

使用 memcmp 一般的には良い考えではありません。より複雑なものから始めて、そこから作業しましょう。


あなたは言及しましたが intdouble, 、最初に集中したいです 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 それらが違うと言うでしょう。

の宣言/初期化の変更 d1d2 上記のコードで:

 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;
  }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top