나는 꽤 이상한 버그를 만났습니다. 다음의 작은 코드는 다소 간단한 수학을 사용합니다.ProGuard가 잘못된 계산을 초래할 수 있습니다.
protected double C_n_k(int n, int k)
{
if(k<0 || k>n)
return 0;
double s=1;
for(int i=1;i<=k;i++)
s=s*(n+1-i)/i;
return s;
}
편집 ProGuard를 사용하면 일부 장치에서 잘못 될 수 있습니다. HTC One S에서 안드로이드 4.1.1 빌드 3.16.401.8 빌드를 확인했지만, 전자 메일로 판단하면 안드로이드 4+를 탑재 한 많은 휴대폰이 영향을받습니다. 그 중 일부 (Galaxy S3)의 경우 미국의 운영 업체 브랜드 휴대폰이 영향을 받지만 국제 버전은 영향을받지 않습니다. 많은 전화는 영향을받지 않습니다.
다음은 1 < = n < 25 및 0 < = k < = n에 대한 C (n, k)를 계산하는 활동 코드입니다. 위에 언급 된 장치에서 첫 번째 세션은 정확한 결과를 제공하지만 후속 시작은 매번 다른 위치에 잘못된 결과를 표시합니다.
방법이 될 수 있습니다
나는 3 개 질문이? ProGuard가 잘못된 것을 만들었지 만 계산은 장치와 세션간에 일관되어야합니다.
어떻게 피할 수 있습니까? 이 경우
double
을long
으로 대체하는 것이 좋습니다. 그러나 이는 보편적 인 방법이 아닙니다.double
을 사용하여 삭제하거나 모호하지 않은 버전을 출시하는 것은 의문의 여지가 있습니다.영향을받는 Android 버전은 무엇입니까? 나는 게임에 고정 꽤 빠르고, 그래서 난 그냥 많은 선수가 그것을 본 것을 알고, 때로는 내가 계산 실수를 볼 수 있기 때문에 적어도 가장 질문에서 안드로이드 4.0
오버플로했다 C(3,3)=3/1*2/2*1/3
. 일반적으로 잘못된 번호는 C (10, ...)의 어딘가에서 시작되며 전화기가 일부 분열을하는 것을 "잊어 버린"것처럼 보입니다.
내 SDK 도구는 22.3 (최신)이며 이클립스와 IntelliJ IDEA에서 만든 빌드에서 본 적이 있습니다.
활동 코드 :
는package com.karmangames.mathtest;
import android.app.Activity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.widget.TextView;
public class MathTestActivity extends Activity
{
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String s="";
for(int n=0;n<=25;n++)
for(int k=0;k<=n;k++)
{
double v=C_n_k_double(n,k);
s+="C("+n+","+k+")="+v+(v==C_n_k_long(n,k) ? "" : " Correct is "+C_n_k_long(n,k))+"\n";
if(k==n)
s+="\n";
}
System.out.println(s);
((TextView)findViewById(R.id.text)).setText(s);
((TextView)findViewById(R.id.text)).setMovementMethod(new ScrollingMovementMethod());
}
protected double C_n_k_double(int n, int k)
{
if(k<0 || k>n)
return 0;
//C_n^k
double s=1;
for(int i=1;i<=k;i++)
s=s*(n+1-i)/i;
return s;
}
protected double C_n_k_long(int n, int k)
{
if(k<0 || k>n)
return 0;
//C_n^k
long s=1;
for(int i=1;i<=k;i++)
s=s*(n+1-i)/i;
return (double)s;
}
}
main.xml에 : 잘못된 계산 결과의
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/text"
android:text="Hello World!"
/>
</LinearLayout>
예 (기억, 그것은 다르다 때마다 나는 그것을 시도)
C(0,0)=1.0
C(1,0)=1.0
C(1,1)=1.0
C(2,0)=1.0
C(2,1)=2.0
C(2,2)=1.0
C(3,0)=1.0
C(3,1)=3.0
C(3,2)=3.0
C(3,3)=1.0
C(4,0)=1.0
C(4,1)=4.0
C(4,2)=6.0
C(4,3)=4.0
C(4,4)=1.0
C(5,0)=1.0
C(5,1)=5.0
C(5,2)=10.0
C(5,3)=10.0
C(5,4)=30.0 Correct is 5.0
C(5,5)=1.0
C(6,0)=1.0
C(6,1)=6.0
C(6,2)=15.0
C(6,3)=40.0 Correct is 20.0
C(6,4)=90.0 Correct is 15.0
C(6,5)=144.0 Correct is 6.0
C(6,6)=120.0 Correct is 1.0
C(7,0)=1.0
C(7,1)=7.0
C(7,2)=21.0
C(7,3)=35.0
C(7,4)=105.0 Correct is 35.0
C(7,5)=504.0 Correct is 21.0
C(7,6)=840.0 Correct is 7.0
C(7,7)=720.0 Correct is 1.0
C(8,0)=1.0
C(8,1)=8.0
C(8,2)=28.0
C(8,3)=112.0 Correct is 56.0
C(8,4)=70.0
C(8,5)=1344.0 Correct is 56.0
C(8,6)=3360.0 Correct is 28.0
C(8,7)=5760.0 Correct is 8.0
C(8,8)=5040.0 Correct is 1.0
C(9,0)=1.0
C(9,1)=9.0
C(9,2)=36.0
C(9,3)=168.0 Correct is 84.0
C(9,4)=756.0 Correct is 126.0
C(9,5)=3024.0 Correct is 126.0
C(9,6)=10080.0 Correct is 84.0
C(9,7)=25920.0 Correct is 36.0
C(9,8)=45360.0 Correct is 9.0
C(9,9)=40320.0 Correct is 1.0
C(10,0)=1.0
C(10,1)=10.0
C(10,2)=45.0
C(10,3)=120.0
C(10,4)=210.0
C(10,5)=252.0
C(10,6)=25200.0 Correct is 210.0
C(10,7)=120.0
C(10,8)=315.0 Correct is 45.0
C(10,9)=16800.0 Correct is 10.0
C(10,10)=1.0
소리가 거의 들리지 않습니다. 그 루프에서's'의 각 값을 로깅하여 계산 방법이 어떻게 다른지 알아 냈습니까? – zapl
"올바른가?" 만약에? – DoubleDouble
수학에서 FWIW는 C (12, 4) = 495입니다. – rgettman