#c #casting #bit-shift #radix-sort
#c #Кастинг #битовый сдвиг #сортировка по основанию
Вопрос:
Я хочу сортировать числа с плавающей запятой в C с помощью основы. Ниже приведен код, который у меня есть. Однако мой вывод неверен. Например, если я запускаю код с 3.1, -5 и 1, мои отсортированные значения печатаются как 3.000000, -5.000000 и 1.000000.
Я знаю, что для правильного преобразования из числа с плавающей запятой в целое число обратно в число с плавающей запятой, мне нужно применить следующую логику, но я не уверен, как интегрировать это в rfloat(), потому что я пытался и получаю много ошибок.
Как я мог бы правильно применить побитовую сортировку по основанию к числам с плавающей точкой?
float x = 3.1, *y;
int *a;
a = (int *)amp;x;
y = (float *)a;
printf("%f",*y);
#include <stdio.h>
#include <stdlib.h>
void rs(unsigned int *a, int c) {
int i;
int m = a[0];
int bt = 0;
unsigned int *b = malloc(0 * sizeof(int));
for (i = 0; i < c; i ) {
if (a[i] > m)
m = a[i];
}
while((m>>bt) > 0){
int buck[2] = { 0 };
for (i = 0; i < c; i ) {
buck[(a[i]>>bt)amp;1] ;
}
for (i = 1; i < 2; i ) {
buck[i] = buck[i-1];
}
for (i = c-1; i >= 0; i--) {
b[--buck[(a[i]>>bt)amp;1]] = a[i];
}
for (i = 0; i < c; i ) {
a[i] = b[i];
}
bt ;
}
free(b);
}
void rfloat(float *arr, int c) {
int d[c];
int i;
for(i = 0; i < c; i ){
d[i] = (int)arr[i];
}
rs(d, c);
for(i = 0; i < c; i ){
arr[i] = (float)d[i];
}
}
int main() {
int size;
int i;
float* arr = malloc(0* sizeof(float));
printf("Size: ");
scanf("%d", amp;size);
for (int i = 0; i < size; i ){
printf("Values: ");
scanf("%f", amp;arr[i]);
}
rfloat(arr, size);
printf("Sorted: ");
for (i = 0; i < size; i ){
printf("%f ", arr[i]);
}
free(arr);
}
Комментарии:
1. Как вы думаете, что это делает:
malloc(0 * sizeof(int));
? Возвращаемое значение будет либо 0, либо указатель, который нельзя разыменовать.2. OT: при компиляции всегда включайте предупреждения, а затем исправляйте эти предупреждения. (для
gcc
минимального использования:-Wall -Wextra -Wconversion -pedantic -std=gnu11
) Примечание: другие компиляторы используют разные параметры для достижения тех же результатов.
Ответ №1:
Положительные числа с плавающей запятой сортируются в том же порядке, что и при сортировке их битового шаблона как целых чисел без знака. Отрицательные числа с плавающей запятой этого не делают, они сортируются в обратном порядке, чем если бы вы сортировали их битовый шаблон. Кроме того, отрицательные числа с плавающей запятой сортируются после положительных, если вы сортируете по их битовому шаблону, потому что установлен их верхний бит.
Итак, что нам делать? Мы выполняем преобразование. Мы переворачиваем все остальные биты, если установлен верхний бит (чтобы отрицательные числа правильно сортировались между собой), и мы всегда переворачиваем верхний бит (чтобы правильно сортировать отрицательные и положительные числа). Затем после сортировки мы меняем преобразование на обратное.
Округление не требуется!
void rfloat(float* arr, size_t size) {
assert(sizeof(unsigned) == sizeof(float) amp;amp; sizeof(float) == 4);
unsigned* d = malloc(size * sizeof(unsigned));
for (size_t i = 0; i < size; i ) {
// Interpret float as 32-bit unsigned.
d[i] = *(unsigned*) amp;(arr[i]);
// Flip all except top if top bit is set.
d[i] ^= (((unsigned) (((int) d[i]) >> 31)) >> 1);
// Flip top bit.
d[i] ^= (1u << 31);
}
rs(d, size);
// Inverse transform.
for (size_t i = 0; i < size; i ) {
d[i] ^= (1u << 31);
d[i] ^= (((unsigned) (((int) d[i]) >> 31)) >> 1);
arr[i] = *(float*) amp;(d[i]);
}
free(d);
}
Обратите внимание, что после этого ваш код по-прежнему не работает. В вашей процедуре сортировки по основанию есть проблемы. Но это уже другой вопрос, если вы сами не можете разобраться.
Комментарии:
1. Есть ли у меня способ сохранить десятичные разряды? Например, если я ввожу -123456.1234567 в качестве одного из значений для сортировки, я хочу, чтобы оно оставалось как -123456.1234567. В настоящее время он печатается как -123456.125000. Я попробовал printf(«.7%f «, arr[i]); но я думаю, что потеря происходит в rfloat() при преобразовании значений.
2. @mathisfun1234 Нет, это фундаментальный предел
float
. Вам нужно будет использоватьdouble
(который также может использовать вышеупомянутый трюк, но вам нужно будет использовать 64-битные целые числа и изменить некоторые константы).