私は NSNumber を使用してさまざまな値を保存していますが、値を使用して計算を行い、結果の新しい NSNumber オブジェクトを初期化するときに問題が発生することがあります。私はそれを克服する方法を考え出しましたが、なぜそれが機能するのかを一生説明することはできませんでした。また、コンピューター環境(double、floatなど)での数値の理解が弱いため、これを尋ねたいと思います学ぶ質問。:-)
最初の例は、異なる測定単位間で変換する場合です。この特定のケースでは、mmol/L と mg/dl の間です。mmol/L 値を表す NSNumber を取得し、その double 値を抽出して計算を実行します。次に、-initWithDouble を使用して新しい NSNumber を作成し、結果を返します。
しかし、私は奇妙なクセを取得します。mmol/L 値が 10.0 の場合、対応する mg/dl 値は 180.0 です (速度は、明らかに単純に 18 です)。しかし、後でユーザーがピッカー ビューで新しい値を選択できるようにし、NSNumber -intValue を使用して現在の値の整数桁を取得する必要がある場合 (小数桁を取得するために独自の拡張機能を使用)、int は 179 です! 計算中にすべての中間 double 値と新しい NSNumber の double 値を確認しましたが、すべて問題ありません (結果は 180.00000 です)。興味深いことに、これはすべての値で発生するわけではなく、一部の値で発生します (10.0 が実際の例です)。
2 番目の例は、Sqlite3 データベースから double 値を取得し、それらを NSNumbers に格納する場合です。繰り返しますが、ほとんどの値は正常に機能しますが、時々奇妙なものが返されます。たとえば、データベースに 6.7 を保存すると (保存時に実際の値であることを確認します)、取得後に NSNumber に表示されるのは 6.699999 です。(これを書いている時点では、それがデータベースにもあるのかどうかは実際には思い出せませんが、そうだと思います - 後で確認できます。)
これらのインスタンスは両方とも、initWithDouble の代わりに中間の float 値と NSNumber initWithFloat を使用することで回避できます。たとえば、私の変換では、float resultAsFloat = resultAsDouble を実行し、新しい NSNumber に initWithFloat を使用します。
長々とした質問で申し訳ありません。また、数値の操作に関する私自身の知識が不足している場合は、申し訳ありませんが、誰かがこれを説明していただければ幸いです。
ありがとう、
アンダース
*編集1 *
単位変換の例のコード:
-(NSNumber *)convertNumber:(NSNumber *)aNumber withUnit:(FCUnit *)aUnit {
// if origin unit and target unit are the same, return original number
if ([aUnit.uid isEqualToString:self.target.uid])
return aNumber;
// determine if origin unit and target unit are comparable
if (aUnit.quantity != self.target.quantity)
return nil;
// if so, convert the number...
// get bases
double originBase;
double targetBase;
if (aUnit.metre != nil) {
originBase = [aUnit.metre doubleValue];
targetBase = [self.target.metre doubleValue];
} else if (aUnit.kilogram != nil) {
originBase = [aUnit.kilogram doubleValue];
targetBase = [self.target.kilogram doubleValue];
} else if (aUnit.second != nil) {
originBase = [aUnit.second doubleValue];
targetBase = [self.target.second doubleValue];
} else if (aUnit.quantity == FCUnitQuantityGlucose) {
// special case for glucose
if ([aUnit.uid isEqualToString:FCKeyUIDGlucoseMillimolesPerLitre]) { // mmol/L -> mg/dl
originBase = 1;
targetBase = 0.0555555555555556; // since 1 / 0.0555555555555556 = 18
} else if ([aUnit.uid isEqualToString:FCKeyUIDGlucoseMilligramsPerDecilitre]) { // mg/dl -> mmol/L
originBase = 0.0555555555555556;
targetBase = 1;
}
}
// find conversion rate
double rate = originBase / targetBase;
// convert the value
double convert = [aNumber doubleValue] * rate;
// TMP FIX: this fixes an issue where the intValue of convertedNumber would be one less
// than it should be if the number was created with a double instead of a float. I have
// no clue as to why...
float convertAsFloat = convert;
// create new number object and return it
NSNumber *convertedNumber = [[NSNumber alloc] initWithFloat:convertAsFloat];
[convertedNumber autorelease];
return convertedNumber;
}