Ответ 1
Вероятно, вы видите ошибки точности из-за компиляции CodeBlocks в 32-битном режиме и компиляции Eclipse в 64-битном режиме:
$ g++ -m32 test.cpp
$ ./a.out
9183
$ g++ -m64 test.cpp
$ ./a.out
9220
Я пишу следующую c++
программу в CodeBlocks
, и результат был 9183. снова я пишу ее в Eclipse
, а после запуска он возвратил 9220. Оба используют MinGW
. Правильный результат - 9183. Что случилось с этим кодом?
Благодарю.
исходный код:
#include <iostream>
#include <set>
#include <cmath>
int main()
{
using namespace std;
set<double> set_1;
for(int a = 2; a <= 100; a++)
{
for(int b = 2; b <= 100; b++)
{
set_1.insert(pow(double(a), b));
}
}
cout << set_1.size();
return 0;
}
Вероятно, вы видите ошибки точности из-за компиляции CodeBlocks в 32-битном режиме и компиляции Eclipse в 64-битном режиме:
$ g++ -m32 test.cpp
$ ./a.out
9183
$ g++ -m64 test.cpp
$ ./a.out
9220
Если я использую оба аргумента в два раза, я получаю то, что вы ожидаете:
pow(static_cast<double>(a), static_cast<double>(b))
На самом деле вы не должны полагаться на ==
(или технически, x <= y && y <= x
) для удвоения в любом случае. Таким образом, этот код создает результаты, зависящие от реализации (строго говоря, UB, за комментарии, но что я имел в виду:))
Разница, по-видимому, связана с тем, используют ли операции с плавающей запятой 53-битную точность или 64-битную точность. Если вы добавите следующие две строки перед циклом (при условии архитектуры Intel), он будет использовать 53-битную точность и даст результат 9220
при компиляции в виде 32-разрядного приложения:
uint16_t precision = 0x27f;
asm("fldcw %0" : : "m" (*&precision));
Это биты 8 и 9 FPU, которые контролируют эту точность. Вышеуказанное устанавливает эти два бита в 10
. Установка их на 11
приводит к 64-битной точности. И только для полноты, если вы установите бит на 00
(значение 0x7f), размер будет напечатан как 9230
.