我有这段代码:
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并报告。
答案 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(以及其他人)将能够帮助你完成任意精确数学。当然,任意精确的数学都会带来性能成本 - 遗憾的是没有免费的午餐。