为了支持小数字,我的变量应该是什么样的?

时间:2013-09-27 06:48:34

标签: objective-c

我有这段代码:

return 1.0 / (1 + exp(-x));

它用于计算给定x的sigmoid函数的值。问题是它总是返回1.00000

我开始浏览代码以查看它失败的地方,我得到了这个:

long double expV = exp(-x);
long double btm = (1 + expV);
long double calc = 1.0 / btw;

现在变量的值是:

(long double) expV = 3.0356148105583944943E-165
(long double) btm = 1
(long double) calc = 1

所以我的问题是如何解决问题,我应该为变量使用其他类型,还是应该在代码中更改某些内容?

更新btm应该是值:1.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030356148105583944943作为WolframAplha说

x的值为1,x的类型为double而不是long double。我将它改为long double并报告。

2 个答案:

答案 0 :(得分:3)

编辑:很抱歉,NSDecimalNumber中的指数支持是-128到127,所以在这种特殊情况下无法工作,否则它对定点算术计算有好处

以前的答案:  NSDecimalNumber

NSDecimalNumber* expV = [NSDecimalNumber decimalNumberWithMantissa:3.0356148105583944943
                                          exponent:-165
                                          isNegative:NO];
NSDecimalNumber* k = [NSDecimalNumber decimalNumberWithString:@"2.0"];

NSDecimalNumber* btm = [expV decimalNumberByAdding:k];

NSDecimalNumber* calc = [k decimalNumberByDividingBy:btm];

可能不是最优雅的方式:/

答案 1 :(得分:3)

这里的问题是long double的精度不足以应对这么小的加法(在btm的情况下)。 '1'超过了小expV,因此,在长双精度内,btm仅为1。

在回答你的问题时,你的代码很好:逻辑上没有错,你只需要一个更精确的数据类型。不幸的是,Objective-C没有提供一个(some discussion here about arbitrary precision in Objective-C)。但是,如果你愿意再远一点,the GNU MP library(以及其他人)将能够帮助你完成任意精确数学。当然,任意精确的数学都会带来性能成本 - 遗憾的是没有免费的午餐。