Что могло заставить детерминированный процесс генерировать ошибки с плавающей точкой

Адаптировал решение из к этому ответу . Разделяет ввод автоматически при вставке запятой (разделитель можно настроить). Создает ImageSpan и ClickableSpan (записи можно удалить, нажав на правую часть).

public class TagEditText extends EditText {

    TextWatcher textWatcher;

    String lastString;

    String separator = ",";

    public TagEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }


    private void init() {
        setMovementMethod(LinkMovementMethod.getInstance());

        textWatcher = new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                String thisString = s.toString();
                if (thisString.length() > 0 && !thisString.equals(lastString)) {
                    format();

                }
            }
        };

        addTextChangedListener(textWatcher);
    }


    private void format() {

        SpannableStringBuilder sb = new SpannableStringBuilder();
        String fullString = getText().toString();

        String[] strings = fullString.split(separator);


        for (int i = 0; i < strings.length; i++) {

            String string = strings[i];
            sb.append(string);

            if (fullString.charAt(fullString.length() - 1) != separator.charAt(0) && i == strings.length - 1) {
                break;
            }

            BitmapDrawable bd = (BitmapDrawable) convertViewToDrawable(createTokenView(string));
            bd.setBounds(0, 0, bd.getIntrinsicWidth(), bd.getIntrinsicHeight());

            int startIdx = sb.length() - (string.length());
            int endIdx = sb.length();

            sb.setSpan(new ImageSpan(bd), startIdx, endIdx, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

            MyClickableSpan myClickableSpan = new MyClickableSpan(startIdx, endIdx);
            sb.setSpan(myClickableSpan, Math.max(endIdx-2, startIdx), endIdx, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

            if (i < strings.length - 1) {
                sb.append(separator);
            } else if (fullString.charAt(fullString.length() - 1) == separator.charAt(0)) {
                sb.append(separator);
            }
        }


        lastString = sb.toString();

        setText(sb);
        setSelection(sb.length());

    }

    public View createTokenView(String text) {


        LinearLayout l = new LinearLayout(getContext());
        l.setOrientation(LinearLayout.HORIZONTAL);
        l.setBackgroundResource(R.drawable.bordered_rectangle_rounded_corners);

        TextView tv = new TextView(getContext());
        l.addView(tv);
        tv.setText(text);
        tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);

        ImageView im = new ImageView(getContext());
        l.addView(im);
        im.setImageResource(R.drawable.ic_cross_15dp);
        im.setScaleType(ImageView.ScaleType.FIT_CENTER);

        return l;
    }

    public Object convertViewToDrawable(View view) {
        int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        view.measure(spec, spec);
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());

        Bitmap b = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);

        Canvas c = new Canvas(b);

        c.translate(-view.getScrollX(), -view.getScrollY());
        view.draw(c);
        view.setDrawingCacheEnabled(true);
        Bitmap cacheBmp = view.getDrawingCache();
        Bitmap viewBmp = cacheBmp.copy(Bitmap.Config.ARGB_8888, true);
        view.destroyDrawingCache();
        return new BitmapDrawable(getContext().getResources(), viewBmp);
    }

    private class MyClickableSpan extends ClickableSpan{

        int startIdx;
        int endIdx;

        public MyClickableSpan(int startIdx, int endIdx) {
            super();
            this.startIdx = startIdx;
            this.endIdx = endIdx;
        }

        @Override
        public void onClick(View widget) {



            String s = getText().toString();

            String s1 = s.substring(0, startIdx);
            String s2 = s.substring(Math.min(endIdx+1, s.length()-1), s.length() );

            TagEditText.this.setText(s1 + s2);
        }

    }
}

R.drawable.bordered_rectangle_ounded_corners:


    
    
    
    

Последнее, что нужно добавить, это png для «x-Button». Пока работает хорошо, единственная проблема в том, что длительное нажатие на клавишу удаления не работает (если у кого-то есть идея, как заставить его работать, не стесняйтесь комментировать)

6
задан Community 23 May 2017 в 10:29
поделиться

1 ответ

Практически в любой ситуации, когда есть быстрый и безопасный режимы, вы найдете какой-то компромисс. В противном случае все работало бы в быстром и безопасном режиме: -).

И, если вы получаете разные результаты с одним и тем же входом, ваш процесс не детерминирован, как бы вы в это ни верите. быть (несмотря на эмпирические данные)

Я бы сказал, что ваше объяснение наиболее вероятно. Переведите его в безопасный режим и посмотрите, исчезнет ли недетерминизм. Это скажет вам наверняка.

Что касается других оптимизаций, если вы компилируете на том же оборудовании с тем же компилятором / компоновщиком и теми же параметрами этих инструментов , он должен сгенерировать идентичный код. Я могу' Я не вижу другой возможности, кроме быстрого режима (или битового гниения в памяти из-за космических лучей, но это маловероятно).

После вашего обновления:

У Intel есть документ здесь , который объясняет некоторые вещи, которые им не разрешено делать в безопасном режиме, включая, помимо прочего:

  • повторное связывание: (a + b) + c -> a + (b + c) .
  • нулевое сворачивание: x + 0 -> x, x * 0 -> 0 .
  • обратное умножение: a / b -> a * (1 / b) .

Хотя вы утверждаете, что эти операции определяются во время компиляции, чипы Intel чертовски умны. Они могут переупорядочивать инструкции, чтобы конвейеры оставались заполненными в многопроцессорных конфигурациях, поэтому, если код специально не запрещает такое поведение, все может измениться во время выполнения (не во время компиляции), чтобы все работало на полной скорости.

13
ответ дан 8 December 2019 в 18:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: