Для цикла в C++ с помощью дважды вспыхивающий один шаг рано, граничное значение, не достигнутое

Это зависит,

я собираюсь идти вразрез с мелкой частицей здесь. Я обычно возвращался бы в блокировке.

Обычно переменная mydata является локальной переменной. Я люблю объявление локальных переменных, в то время как я инициализирую их. У меня редко есть данные для инициализации моего возвращаемого значения за пределами моей блокировки.

, Таким образом, Ваше сравнение на самом деле испорчено. В то время как идеально различие между этими двумя опциями было бы, как Вы записали, который, кажется, дает поклон для преобразования регистра 1, на практике это немного более ужасно.

void example() { 
    int myData;
    lock (foo) { 
        myData = ...;
    }
    return myData
}

по сравнению с

void example() { 
    lock (foo) {
        return ...;
    }
}

я нахожу, что случай 2 значительно легче читать и тяжелее завинтить, специально для коротких отрывков.

5
задан Ahmed Said 17 August 2009 в 06:36
поделиться

9 ответов

При использовании значений с плавающей запятой не каждое значение может быть точно представлено, 0,95 + 0,05> 1 , поскольку 0,95 не может быть точно представлено в double value.

Посмотрите, что Википедия говорит о точности операций с плавающей запятой .

Если вы посмотрите на конвертер с плавающей запятой IEEE , вы увидите, что значение 0,95 в 64-битном формате с плавающей запятой ( double ) составляет 0-01111111110-1110011001100110011001100110011001100110011001100110 , введя его в калькулятор с плавающей запятой получить значение 0,95000016 и прибавив к нему 0,05 , вы перейдете к отметке 1,0 .

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

18
ответ дан 18 December 2019 в 05:13
поделиться

Обычно, когда вы сравниваете числа типа double, простого сравнения недостаточно, и вы должны сравнивать их «с точностью». например:

if ( fabs(double1-double2) < 0.0000001 ) {
  do-something
}

Проблема возникает из-за представления переменных типа double .

11
ответ дан 18 December 2019 в 05:13
поделиться

Как упоминалось другими, это хорошо известная проблема из-за неточного представления некоторых десятичных чисел в памяти. Я настоятельно рекомендую прочитать Что должен знать каждый компьютерный ученый об арифметике с плавающей запятой и Представления реальных чисел с плавающей запятой IEEE номера .

6
ответ дан 18 December 2019 в 05:13
поделиться

Вы не должны использовать == или <= для чисел типа double из-за его внутреннего представления. На последнем шаге вы получите 0.95000000000000029 . Вместо этого вы можете использовать следующий код:

stepSize = 0.05;
// stepSize/2 looks like a good delta for most cases
for (double index = rangeMin; index < rangeMax+stepSize/2; index+= stepSize)
{
    cout << index << endl;
}

Подробнее см. Что должен знать каждый компьютерный ученый об арифметике с плавающей запятой .

6
ответ дан 18 December 2019 в 05:13
поделиться

Наиболее точные десятичные дроби не имеют точного конечного представления в арифметике с плавающей запятой.

Вам нужно прочитать Что каждый компьютерный ученый должен знать об арифметике с плавающей точкой Голдберга. .

4
ответ дан 18 December 2019 в 05:13
поделиться

Вероятно, последнее значение индекса будет иметь вид 1.00000001 .

2
ответ дан 18 December 2019 в 05:13
поделиться

Это связано с неточным представлением десятичных дробей числами с плавающей запятой. Ваш размер шага на самом деле не 0,1 или 0,05, это какое-то другое значение, которое очень близко. Небольшая ошибка накапливается по мере прохождения цикла.

Чтобы решить эту проблему, вы должны избегать сравнения чисел с плавающей запятой на предмет равенства.

1
ответ дан 18 December 2019 в 05:13
поделиться

Как говорили другие, не каждое действительное число точно может быть представлено как значение с плавающей запятой, поэтому вы можете ожидать небольшую «случайную» ошибку округления при вычислениях с плавающей запятой. Это похоже на то, что происходит с обычными десятичными цифрами: 1/3 не может быть точно представлена ​​с использованием трех десятичных цифр (0,33), поэтому (1/3) * 3 станет 0,99, а не точно 1.

используйте некоторую «точность» в своих сравнениях, но я бы рекомендовал избегать чисел с плавающей запятой для циклов и вместо этого использовать целые числа.

Например, ваш цикл

stepSize = 0.05;
for (double index = rangeMin; index <= rangeMax; index+= stepSize)
{
    cout << index << endl;
}

может быть заменен чем-то вроде

stepSize = 0.05;
for (int index = 0; index < 21; ++index)
{
    double value = rangeMin + index * stepSize;
    cout << value << endl;
}
]
2
ответ дан 18 December 2019 в 05:13
поделиться

См. Этот вывод: (точность с плавающей запятой)

#include <iostream>
#include <iomanip>
using namespace std;
int main(){
    double rangeMin = 0.0;
    double rangeMax = 1.0;
    double stepSize = 0.1;
    double index;
    for (index = rangeMin;  index <= rangeMax; index+=stepSize)
        {
               cout << fixed << setprecision(16) <<  index << endl;
         }
  cout << endl;
  stepSize = 0.05;
  for (index = rangeMin; index<= rangeMax; index+= stepSize)
     {
         cout << index << endl;
             }

   cout << "\n" << setprecision(16) << index << " "  << rangeMax;
   if(index==rangeMax)
      cout << "\nEQ";
   else
     cout << "\nNot EQ";
     return 0;
}

0.0000000000000000
0.1000000000000000
0.2000000000000000
0.3000000000000000
0.4000000000000000
0.5000000000000000
0.6000000000000000
0.7000000000000000
0.7999999999999999
0.8999999999999999
0.9999999999999999

0.0000000000000000
0.0500000000000000
0.1000000000000000
0.1500000000000000
0.2000000000000000
0.2500000000000000
0.3000000000000000
0.3500000000000000
0.4000000000000000
0.4500000000000000
0.4999999999999999
0.5499999999999999
0.6000000000000000
0.6500000000000000
0.7000000000000001
0.7500000000000001
0.8000000000000002
0.8500000000000002
0.9000000000000002
0.9500000000000003

1.0000000000000002 1.0000000000000000
Not EQ
1
ответ дан 18 December 2019 в 05:13
поделиться
Другие вопросы по тегам:

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