ipGlobalProperties.GetActiveTcpConnections()
не возвращается, соединения в Слушают состояние.
Порт может использоваться для слушания, но без одного связанного с ним выше не будет работать метод, описанный.
На самом деле, это не C ++, а математический вопрос.
РЕДАКТИРОВАТЬ:
Как сказал Кругар, статья, на которую я указал, не отвечает ни на что. Конечно, там нет прямого ответа на твой вопрос, Фени. Я просто подумал, что основная проблема, с которой вы столкнулись, - это точность с плавающей запятой, и, может быть, вы захотели немного математики для решения вашей проблемы.
Для нетерпеливых есть ссылка в статье на подробное обсуждение реализации isqrt ].
Если вы не хотите полагаться на точность с плавающей запятой, вы можете использовать следующий код, который использует целочисленную математику.
Isqrt взят из здесь и является O (log n)
// Finds the integer square root of a positive number
static int Isqrt(int num)
{
if (0 == num) { return 0; } // Avoid zero divide
int n = (num / 2) + 1; // Initial estimate, never low
int n1 = (n + (num / n)) / 2;
while (n1 < n)
{
n = n1;
n1 = (n + (num / n)) / 2;
} // end while
return n;
} // end Isqrt()
static bool IsPerfectSquare(int num)
{
return Isqrt(num) * Isqrt(num) == num;
}
Чтобы не делать один и тот же расчет дважды, я бы сделал это с временным номером:
int b = (int)sqrt((float)a);
if((b*b) == a)
{
//perfect square
}
редактировать: Дэв сделал хорошее замечание. вместо того, чтобы полагаться на приведение, вам нужно сначала округлить число с плавающей запятой
, поэтому оно должно быть:
int b = (int) (sqrt((float)a) + 0.5f);
if((b*b) == a)
{
//perfect square
}
На ваш вопрос уже был дан ответ, но вот рабочее решение.
Ваши «идеальные квадраты» неявно являются целочисленными значениями, поэтому вы можете легко решить проблемы точности, связанные с форматом с плавающей запятой, используя некоторая функция квадратного корня целого числа для определения квадратного корня целого числа из значения, которое вы хотите проверить. Эта функция вернет наибольшее число r
для значения v
, где r * r <= v
. Когда у вас есть r
, вам просто нужно проверить, r * r == v
.
unsigned short isqrt (unsigned long a)
{
unsigned long rem = 0;
unsigned long root = 0;
for (int i = 16; i; i--) {
root <<= 1;
rem = ((rem << 2) + (a >> 30));
a <<= 2;
if (root < rem)
rem -= ++root;
}
return (unsigned short) (root >> 1);
}
bool PerfectSquare (unsigned long a)
{
unsigned short r = isqrt (a);
return r * r == a;
}
Я не следовал формуле, прошу прощения. Но вы можете легко проверить, является ли число с плавающей запятой целым числом, преобразовав его к целочисленному типу и сравнив результат с числом с плавающей запятой. Итак,
bool isSquare(long val) {
double root = sqrt(val);
if (root == (long) root)
return true;
else return false;
}
Естественно, это возможно только в том случае, если вы работаете со значениями, которые, как вы знаете, будут соответствовать диапазону целочисленных типов. Но в этом случае вы можете решить проблему таким образом, избавив вас от присущей математической формулы сложности.
сначала основы:
if вы (int) число в вычислении удалит ВСЕ данные после запятой. Если я правильно помню свой C, если у вас есть (int) в любом вычислении (+ / - *), он автоматически будет предполагать int для всех других чисел.
Итак, в вашем случае вы хотите float для каждого задействованного числа, иначе вы потеряет данные:
Математика с плавающей запятой по своей природе неточна.
Рассмотрим этот код:
int a=35;
float conv = (float)a;
float sqrt_a = sqrt(conv);
if( sqrt_a*sqrt_a == conv )
printf("perfect square");
вот что произойдет:
a = 35
conv = 35.000000
sqrt_a = 5.916079
sqrt_a*sqrt_a = 34.999990734
совершенно ясно, что sqrt_a ^ 2 не равно А.
Я бы сделал.
// sqrt always returns positive value. So casting to int is equivalent to floor()
int down = static_cast<int>(sqrt(value));
int up = down+1; // This is the ceil(sqrt(value))
// Because of rounding problems I would test the floor() and ceil()
// of the value returned from sqrt().
if (((down*down) == value) || ((up*up) == value))
{
// We have a winner.
}
Как говорит Райниер, вам нужно добавить 0,5, чтобы обеспечить округление до ближайшего целого числа, поэтому вы получите
int b = (int) (sqrt((float)a) + 0.5f);
if((b*b) == a) /* perfect square */
Чтобы это сработало, b
должно быть (точно) равно квадратному корню из a
, если a
- полный квадрат. Однако я не думаю, что это можно гарантировать. Предположим, что int
составляет 64 бита, а float
- 32 бита (я думаю, что это разрешено). Тогда a
может иметь порядок 2 ^ 60, поэтому его квадратный корень имеет порядок 2 ^ 30. Однако float
хранит только 24 бита в мантиссе, поэтому ошибка округления имеет порядок 2 ^ (30-24) = 2 ^ 6. Это больше 1, поэтому b
может содержать неправильное целое число. Например, я думаю, что приведенный выше код не идентифицирует a
= (2 ^ 30 + 1) ^ 2 как полный квадрат.
Более очевидный, если медленнее - O (sqrt (n)) - способ:
bool is_perfect_square(int i) {
int d = 1;
for (int x = 0; x <= i; x += d, d += 2) {
if (x == i) return true;
}
return false;
}
В то время как другие отмечали, что вам не следует проверять равенство с помощью чисел с плавающей запятой, я думаю, что вы упускаете шансы воспользоваться преимуществами свойств идеальных квадратов. Во-первых, нет смысла заново возводить вычисленный корень в квадрат. Если a
представляет собой полный квадрат, тогда sqrt (a)
является целым числом, и вы должны проверить:
b = sqrt((float)a)
b - floor(b) < e
где e
задано достаточно малым. Есть также ряд целых чисел, которые можно исключить как неквадратные, прежде чем извлекать квадратный корень. Проверяя Википедию , вы можете увидеть некоторые необходимые условия для того, чтобы a
было квадратом:
Квадратное число может заканчиваться только на digits 00,1,4,6,9, or 25 in base 10
Another simple check would be to see that a % 4 == 1 or 0
before taking the root since:
Squares of even numbers are even, since (2n)^2 = 4n^2.
Squares of odd numbers are odd, since (2n + 1)^2 = 4(n^2 + n) + 1.
These would essentially eliminate half of the integers before taking any roots.
Самое чистое решение - использовать целочисленную подпрограмму sqrt, а затем выполнить:
bool isSquare( unsigned int a ) {
unsigned int s = isqrt( a );
return s * s == a;
}
Это будет работать в полном диапазоне int и с идеальной точностью. Несколько случаев:
a = 0, s = 0, s * s = 0 (add an exception if you don't want to treat 0 as square)
a = 1, s = 1, s * s = 1
a = 2, s = 1, s * s = 1
a = 3, s = 1, s * s = 1
a = 4, s = 2, s * s = 4
a = 5, s = 2, s * s = 4
Не потерпит неудачу, когда вы приблизитесь к максимальному значению для вашего размера int. Например, для 32-битных целых чисел:
a = 0x40000000, s = 0x00008000, s * s = 0x40000000
a = 0xFFFFFFFF, s = 0x0000FFFF, s * s = 0xFFFE0001
Используя числа с плавающей запятой, вы можете столкнуться с рядом проблем. Вы можете обнаружить, что sqrt (4) = 1.999999 ...
, и аналогичные проблемы, хотя вы можете округлить до ближайшего вместо использования floor ()
.
Хотя хуже , float имеет только 24 значащих бита, что означает, что вы не можете преобразовать int больше 2 ^ 24-1 в float без потери точности, что приводит к ложным срабатываниям / отрицаниям. Однако с использованием удвоений для тестирования 32-битных целых чисел все будет в порядке.
Но не забудьте вернуть результат sqrt с плавающей запятой обратно в int и сравнить результат с исходным int. Сравнение поплавков никогда не бывает хорошей идеей; даже для квадратных значений x в ограниченном диапазоне нет гарантии, что sqrt (x) * sqrt (x) == x
или что sqrt (x * x) = x
.