2017-08-11 1 views
0

Je stocke une valeur longue vient du système backend et j'ai dû le convertir en flottant parce que l'un des api tiers comprend seulement float. Maintenant, quand je relis le flotteur et que j'essaie de le reconvertir longtemps, je reçois un nombre plus important (certaines fois j'ai vu plus petit aussi) que ce que j'avais.float à long conversion augmentant la valeur

Ma question est comment puis-je récupérer le numéro d'origine en longueur. Je suis heureux d'ajouter toute logique d'arrondi si nécessaire

public class Main { 

    public static void main(String[] args) { 


     long item = 1502028000; 

     System.out.println(String.format("item -> %d",item)); 

     float floatItem = item; 

     System.out.println(String.format("floatItem -> %f",floatItem)); 

     long resultItem = (long)floatItem; 

     System.out.println(String.format("resultItem -> %d",resultItem)); 

    } 
} 

Ci-dessous la sortie. J'ai besoin de mon numéro d'origine qui est 1502028000 dans ce cas.

item -> 1502028000 
floatItem -> 1502028032.000000 
resultItem -> 1502028032 
+5

Vous ne pouvez pas flotter à long est une conversion avec perte (également à long flottant). –

+0

Pouvez-vous utiliser 'double' à la place? – shmosel

+0

Non seulement j'ai l'option d'utiliser float. Je ne peux pas modifier l'API tierce. Pouvons-nous faire un peu de Math.round ou quelque chose pour obtenir le numéro d'origine – Bulu

Répondre

0

Une valeur flottante a seulement ~ 24 bits significatifs, une longue a 64 bits. Il doit donc arriver que certaines/longues valeurs différentes donnent la même valeur flottante. Et cela ne peut pas être récupéré.

Vous avez dit que vos positions longues sont toujours des multiples de 1000. Donc, parmi les nombreux longs qui correspondent à votre flottant donné, seuls les divisibe de 1000 sont valables pour vous. C'est ce que votre suggestion d'arrondi Math.round(value/1000)*1000 utilisera. Mais cela ne fonctionne que jusqu'à ce qu'il y ait plus de 1000 longs mappages à un flotteur, et cela se produit autour de la magnitude de 10 milliards. Votre exemple est juste un facteur inférieur à dix, donc cela ne va pas aider de manière fiable si les chiffres peuvent augmenter. Si vous devez vraiment retourner la valeur float à l'original long (demandez-vous: pourquoi est-il nécessaire - puis-je faire mon travail d'une autre manière?), Vous pouvez maintenir une valeur Map from Float aux valeurs Long originales vous passez un long à la bibliothèque de tiers. Si les valeurs longues sont rares, il est probable que dans les valeurs longues valides que vous avez utilisées, vous pouvez souvent recadrer à partir de float sans ambiguïté.

Mais c'est un méchant kludge. Soyez prêt à faire face à l'ambiguïté si cela se produit.

+1

Alors que c'est presque vrai (ces ~ 24 bits significatifs), ce n'est pas toute la vérité. Le fait que les flottants aient un exposant signifie que d'autres valeurs peuvent également être représentées, mais pas toutes. J'aurais fait remarquer qu'un flotteur a généralement 32 bits, donc il est clair qu'il ne peut pas avoir une représentation différente pour chaque valeur de 64 bits. En raison de la façon dont il est composé, il peut également représenter des valeurs assez grandes, mais pas toutes avec précision. –

3

La réponse courte est qu'une valeur float est seulement précis à environ 7 chiffres. En termes de la valeur long vous convertissez en un flottant, cela signifie que le float ne peut conserver que les 7 premiers chiffres de 1502028000. Notez que ces 7 sont toujours conservés dans la valeur float et quand vous revenez à un long.

Si vous souhaitez en savoir plus sur la précision du flotteur, jetez un oeil à this. Juste comme un exercice, vous pouvez faire la même chose avec un double et plus de chiffres doivent être conservés.

+0

Double fonctionne toujours mais je ne peux pas – Bulu

+1

Un double ne se produit que pour les cas que vous lui donnez mais il se casserait aussi à un certain point. Il a juste une plus grande précision car si est représenté par 64 bits pas 32 comme un flotteur –

0

Il semble que float n'a pas assez de taille pour convertir une valeur "longue" et donc lors de la conversion, il perd sa précision.

Pour résoudre ce problème, vous pouvez utiliser double au lieu de float. Cela conservera votre valeur après la double conversion que vous faites.

long item = 1502028000; 
double floatItem = (double)item; 
long resultItem = (long)floatItem; 
System.out.println(String.format("resultItem -> %d",resultItem)); 

Cette impression:

resultItem -> 1502028000 
+1

Même le double ne sera pas suffisant pour toute la gamme de valeur de long. –