2012-06-07 20 views
0

我在動作號碼,通過一些任意數學到達:期截斷的Actionscript數

var value:Number = 45 * (1 - (1 /3)); 
trace(value);//30.00000000004 

現在,我想借這個數字的上限,但在情況下,量是大於下一個較小的整數小於某個ε。在上面的例子中,我真想四捨五入到30,但只有在我知道我得到一個舍入誤差的情況下:

Math.ceil(value); //I want 30, but get 31 
Math.ceil(30.1); //In this case, it's reasonable to get 31 

有截斷ActionScript中的號碼一個優雅的方式?或者容易丟棄少於某個eps的數字的任何部分?

+0

你確定第一段代碼實際上沒有給你一個30的整數嗎?它出於某種原因爲我服務。只是好奇。 –

+0

在Flash Builder中,它肯定顯示爲非整數。爲了清晰起見,我所省略的具體數學:足以說,當乘以0.666(某些數字爲6)667時,我得到了30.000(某個數字爲0)0004。 –

回答

1
var value:Number = 45 * (1 - (1 /3)); 
trace(value);//30.00000000004 

// Play with arbitraryPrecision until you are satisfied with 
// the accuracy of your results 
var arbitraryPrecision:int = 3; 
var fixed:Number = value.toFixed(arbitraryPrecision); 

trace(Math.ceil(fixed)); 
+0

我的理解(http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Number.html#toFixed%28%29)是toFixed返回一個字符串。最優雅的解決方案是否真的把它轉換回數字? –

+0

有趣。甚至沒有意識到toFixed()返回了一個字符串。這是我能想到的唯一不需要手動操作的簡單解決方案。 –

+0

順便說一句,我期望AS3編譯器優化此字符串<->編號,所以我不認爲性能影響將是重要的,如果有的話。今天晚些時候試驗這個,併發布一些結果。 –

2

此方法對您有幫助嗎?

var precision:int = 4; 
var isActualCeilingValRequred:Boolean; 
var thresholdValForCeiling:int = 100; 

private function getCeilingValue(num:Number):Number 
{ 
    var tempNum = num * Math.pow(10, precision); 
    var decimalVal = tempNum % Math.pow(10, precision); 

    if(decimalVal < thresholdValForCeiling) { 
    return Math.floor(num); 
    } else { 
    return Math.Ceil(num); 
    } 
} 
+0

我是upvoting,因爲這是一個體面的epsilon處理程序,但爲什麼我要問的部分原因是我期望這被稱爲很多次,並且具有多個變量實例的整個函數可能是矯枉過正。雖然我可能只是像這樣向我的數學實用程序添加更流暢的功能來幫助您。 :/ –

0

四捨五入的數的小數位指定數目的基本方法是乘以10 ^數字的數目由相同的小數點DIGITS位左移,執行舍入,和除法10^DIGITS將小數點移回右側。

var value:Number = 45 * (1 - (1/3)); 
trace(value); // 30.000000000000004 
trace(Math.ceil(value)); // 31 
// Round the number to 13 decimal digits. 
const POWER:Number = 1e13; 
value = Math.round(value * POWER)/POWER; 
trace(value); // 30 
// Compute number's ceiling. 
value = Math.ceil(value); 
trace(value); // 30` 

它適用於您的示例,但有一個大問題。如果您將您的價值更改爲450 * (1 - (1/3));,您的原始問題將再次出現。現在擺脫它,你將不得不四捨五入到十二進制數字。基本上,雙精度格式(數字)的有效位數可以保存約15位有效數字。這意味着當數值增加十倍時,小數點向左移動,並且您想要擺脫的最後一個「4」數字越來越接近小數點。所以代碼變得更加複雜。

var value:Number = 450 * (1 - (1/3)); 
trace(value); // 30.000000000000004 
trace(Math.ceil(value)); // 31 
var exp:Number = Math.floor(Math.log(Math.abs(value)) * Math.LOG10E); 
trace('exp=' + exp); // exp=2 
const POWER:Number = Math.pow(10, 14 - exp); 
value *= POWER; 
trace(value); // 300000000000000.06 
value = Math.round(value); 
trace(value); // 300000000000000 
value /= POWER; 
trace(value); // 300 

正如你所看到的,它現在可以工作,不管值的大小。 首先,我通過以數字的絕對值的10對數爲底的對數來找到數字的指數,然後將其舍入。如果您計算a = value * Math.pow(10, exp);,則值可以表示爲a * 10^b,其中(1≤| a | < 10),稱爲標準化科學記數法。但這不是我們在這裏做的。現在我們知道小數點左邊有多少數字,我們將右移小數點,但不要太遠,以保留一個0和我們想要擺脫的錯誤數字,在右邊的小數點。因此,乘以10 ^(14-exp),輪,然後除以相同的權力。