3 回答

TA貢獻1815條經驗 獲得超6個贊
這是Java中的相同代碼,沒有12.100000000000001錯誤,其他答案也有
我還刪除了重復的代碼,更改power為整數類型以防止n - d完成操作時出現浮動問題,并使長中間體更加清晰
該錯誤是由大量乘以少量引起的。相反,我將兩個相似大小的數字相除。
編輯
修正了更多的錯誤。添加了對0的檢查,因為這會導致NaN。使函數實際使用負數(原始代碼不處理負數,因為負數的對數是復數)
public static double roundToSignificantFigures(double num, int n) {
if(num == 0) {
return 0;
}
final double d = Math.ceil(Math.log10(num < 0 ? -num: num));
final int power = n - (int) d;
final double magnitude = Math.pow(10, power);
final long shifted = Math.round(num*magnitude);
return shifted/magnitude;
}

TA貢獻1799條經驗 獲得超8個贊
這是一個簡短而有趣的JavaScript實現:
function sigFigs(n, sig) {
var mult = Math.pow(10, sig - Math.floor(Math.log(n) / Math.LN10) - 1);
return Math.round(n * mult) / mult;
}
alert(sigFigs(1234567, 3)); // Gives 1230000
alert(sigFigs(0.06805, 3)); // Gives 0.0681
alert(sigFigs(5, 3)); // Gives 5

TA貢獻1825條經驗 獲得超6個贊
摘要:
double roundit(double num, double N)
{
double d = log10(num);
double power;
if (num > 0)
{
d = ceil(d);
power = -(d-N);
}
else
{
d = floor(d);
power = -(d-N);
}
return (int)(num * pow(10.0, power) + 0.5) * pow(10.0, -power);
}
因此,您需要找到第一個非零數字的小數位,然后保存下N-1個數字,然后根據其余數字舍入第N個數字。
我們可以使用日志來做第一個。
log 1239451 = 6.09
log 12.1257 = 1.08
log 0.0681 = -1.16
因此,對于大于0的數字,請取對數的上限。對于數字<0,請使用日志的底數。
現在我們有數字d:第一種情況為7,第二種情況為2,第三種情況為-2。
我們必須將(d-N)數字四舍五入。就像是:
double roundedrest = num * pow(10, -(d-N));
pow(1239451, -4) = 123.9451
pow(12.1257, 1) = 121.257
pow(0.0681, 4) = 681
然后執行標準的舍入操作:
roundedrest = (int)(roundedrest + 0.5);
并撤消戰俘。
roundednum = pow(roundedrest, -(power))
功率是上面計算出的功率。
關于準確性:Pyrolistical的答案確實更接近實際結果。但是請注意,無論如何您都不能完全代表12.1。如果按以下方式打印答案:
System.out.println(new BigDecimal(n));
答案是:
Pyro's: 12.0999999999999996447286321199499070644378662109375
Mine: 12.10000000000000142108547152020037174224853515625
Printing 12.1 directly: 12.0999999999999996447286321199499070644378662109375
因此,請使用Pyro的答案!
添加回答
舉報