1

我在我的 iPhone 上运行这段代码:

double d = DBL_MAX;
NSString *s = [NSString stringWithFormat:@"%.0f", d];
double dp = atof([s cStringUsingEncoding:[NSString defaultCStringEncoding]]);
NSString *pe = d == dp ? @"YES" : @"NO";

double one = 1;
double dpd = dp / one;
NSString *de = d == dpd ? @"YES" : @"NO";

NSLog(@"### Parsed are equal: %@, divided are equal: %@", pe, de);
NSLog(@"D   : %.0f", d);
NSLog(@"DP  : %.0f", dp);
NSLog(@"DPD : %.0f", dpd);

...并获得此输出:

### Parsed are equal: NO, divided are equal: NO
D   : 17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817154045895351438246423432132688946418276846754670353751698604991057655128207624549009038932894407586850845513394230458323690322294816580855933212334827479
DP  : 17976931348623155723920577891946972866121062246621938439403251722449088432276750723756897307653964877256701669823356283705419341284625019355047863102662518251134787976961389628366367996124520722972986881016593281354069269901878996004952428787693676134400
DPD : 17976931348623155723920577891946972866121062246621938439403251722449088432276750723756897307653964877256701669823356283705419341284625019355047863102662518251134787976961389628366367996124520722972986881016593281354069269901878996004952428787693676134400

printf()为什么/序列atof()失去精度(我假设stringWithFormatprintf内部)?它不仅发生在 DBL_MAX 上,而且发生在每个非常大的数字上(即10000它按预期工作,因为DBL_MAX / 2它没有)。有没有办法避免它?

4

2 回答 2

2

并非所有小数都可以用二进制表示。例如 0.2(dec) = 0.001100110011...(bin)。因此,当数字从十进制字符串转换时,它有时会被截断(或四舍五入)。

当从二进制转换为十进制时,即使总是有可能,结果有时也会比 n*log_10(2) 长,其中 n 是二进制位数。例如 0.001(bin) = 0.125(dec),但 3*log_10(2)=0.903... 因此,当数字从二进制转换为数字字符串时,有时也会被截断。

这就是为什么你得到的结果略有不同的原因。

这是一个例子。假设你的尾数是 6 位数。让我们将数字 0.001111(bin) 转换为十进制。精确的结果是 0.234375,但是这个数字被四舍五入到 0.23,因为您只需要 6*log_10(2)=1.8061 位来表示任何 6 位二进制。在这种情况下,1.8061 甚至四舍五入为 2。

现在让我们看看如果我们将 0.23 转换回二进制会得到什么。它是 0.0011101011... 这必须四舍五入,结果可能是 0.001110 或 0.001111,具体取决于四舍五入的方式。

于 2012-03-13T07:20:59.223 回答
1

“显着”,double 有 53 位精度,即 15 到 16 位十进制数字,您在第 17 位有差异(但第一个数字是 1)。

我的猜测(我没有检查过)是差异仅在于双精度的次要位,因此在输出或输入例程中都是舍入问题。我不知道在这种情况下目标 C 是否要求正确的结果(正确的结果要求使用多精度算术),我知道 C 实现会有所不同。

于 2012-03-12T17:19:52.880 回答