Ich habe festgestellt, dass eine meiner Anwendung auf dem Markt veröffentlicht seltsame Ergebnisse auf einigen Telefonen. Bei der Untersuchung stellt sich heraus, dass es ein Problem mit einer Funktion gibt, die den Abstand zwischen zwei GeoPoints berechnet - manchmal gibt es einen völlig falschen Wert zurück. Dieses Problem reproduziert nur auf Geräten mit MediaTek MT6589 SoC (aka MTK6589). Und AFAIK alle diese Geräte haben Android 4.2 installiert.Doppelte Genauigkeit Wert Rechenfehler auf MediaTek Prozessoren
aktualisiert war ich auch in der Lage, den Fehler auf Lenovo S6000 Tablet mit MediaTek MT8125/8389 Chip zu reproduzieren und auf Fly IQ444 Quattro mit MT6589 und mit Android 4.1 installiert.
Ich erstellte ein Testprojekt, das hilft, den Fehler zu reproduzieren. Es führt Berechnungen wiederholt für 1'000 oder 100'000 Iterationen durch. Um mögliche Threading-Probleme auszuschließen, wird die Berechnung auf dem UI-Thread ausgeführt (mit kleinen Pausen, um die Benutzeroberfläche zu erhalten). Im Testprojekt verwendete ich nur einen Teil aus der ursprünglichen Abstandsformel:
private double calcX() {
double t = 1.0;
double X = 0.5 + t/16384;
return X;
}
Wie Sie sich auf web2.0calc.com überprüfen kann der Wert von X
sollte etwa sein: 0.50006103515625
.
Allerdings wird auf den Geräten mit MT6589-Chip oft der falsche Wert berechnet: 2.0
. Das Projekt ist available at Google Code (APK ist auch verfügbar). Die Quelle der Testklasse ist im folgenden dargestellt:
public class MtkTestActivity extends Activity {
static final double A = 0.5;
static final double B = 1;
static final double D = 16384;
static final double COMPUTED_CONST = A + B/D;
/*
* Main calculation where bug occurs
*/
public double calcX() {
double t = B;
double X = A + t/D;
return X;
}
class TestRunnable implements Runnable {
static final double EP = 0.00000000001;
static final double EXPECTED_LOW = COMPUTED_CONST - EP;
static final double EXPECTED_HIGH = COMPUTED_CONST + EP;
public void run() {
for (int i = 0; i < SMALL_ITERATION; i++) {
double A = calcX();
if (A < EXPECTED_LOW || A > EXPECTED_HIGH) {
mFailedInCycle = true;
mFails++;
mEdit.getText().append("FAILED on " + mIteration + " iteration with: " + A + '\n');
}
mIteration++;
}
if (mIteration % 5000 == 0) {
if (mFailedInCycle) {
mFailedInCycle = false;
} else {
mEdit.getText().append("passed " + mIteration + " iterations\n");
}
}
if (mIteration < mIterationsCount) {
mHandler.postDelayed(new TestRunnable(), DELAY);
} else {
mEdit.getText().append("\nFinished test with " + mFails + " fails");
}
}
}
public void onTestClick(View v) {
startTest(IT_10K);
}
public void onTestClick100(View v) {
startTest(IT_100K);
}
private void startTest(int iterationsCount) {
Editable text = mEdit.getText();
text.clear();
text.append("\nStarting " + iterationsCount + " iterations test...");
text.append("\n\nExpected result " + COMPUTED_CONST + "\n\n");
mIteration = 0;
mFails = 0;
mFailedInCycle = false;
mIterationsCount = iterationsCount;
mHandler.postDelayed(new TestRunnable(), 100);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler(getMainLooper());
mEdit = (EditText) findViewById(R.id.edtText1);
}
private static final int IT_10K = 1000;
private static final int IT_100K = 100000;
private static final int SMALL_ITERATION = 50;
private static final int DELAY = 10;
private int mIteration;
private int mFails;
private boolean mFailedInCycle;
private Handler mHandler;
private int mIterationsCount;
private EditText mEdit;
}
Um das Problem zu beheben, es reicht nur alle Methode double
zu float
in calcX()
zu ändern.
Weitere Untersuchungen
Turning JIT aus (von android:vmSafeMode="true"
zum App-Manifest Hinzufügen) behebt auch Fehler.
Hat jemand diesen Bug schon mal gesehen? Vielleicht ist das ein bekanntes Problem?
ps.s .: wenn jemand in der Lage wäre, diesen Fehler auf dem Gerät mit anderen Chip zu reproduzieren, oder könnte es mit jedem MediaTek-Chip und Android> = 4.3 testen, werde ich es sehr zu schätzen wissen.
https://code.google.com/p/android/issues/detail?id=63790 Details, was auf dem HTC One S Geräte wie genau dieses Problem sieht Android 4.1.1 läuft, sowie eine Reihe von anderen Geräten . In diesem Fehler sieht es anfangs wie eine schlechte Interaktion mit ProGuard aus, aber weitere Analyse hat es auf einen kleineren Dalvik Bytecode reduziert. Die Ursache wurde noch nicht ermittelt, und die einzige Problemumgehung ist die, die Sie entdeckt haben, um das JIT zu deaktivieren. –
Ja, es scheint sehr ähnlich zu dem, was ich gepostet habe. Ein Link zu Google-Code enthält eine Test-App, die Sie ausprobieren können, und [hier] (http: // stackoverflow.com/questions/20573598/progard-cause-increase-calculations) ist eine detailliertere Beschreibung und Diskussion mit dem Entwickler von ProGuard. – Dmitry
Ich kann diesen Fehler in einem MT6589-Telefon (Canvas HD) mit Android 4.2.1 reproduzieren. – HackToHell