Ontleed lang dubbel van tekenreeks

Ik moet drijvende-komma-letterwoorden in C-code ontleden met OCaml.

OCAML's zweeftype is 64 bit. Ik heb de string van de letterlijke, de numerieke waarde afgerond op 64 bits en de aard ervan (float, double of long double).

Het probleem is letterlijk met een numerieke waarde groter dan 64 bit:

  1. lange dubbele letterlijke waarden
  2. float-literals met 'f'-suffix waarvoor dubbele afrondingsfouten zouden optreden als ze niet het achtervoegsel zouden hebben.

OCaml's arbitraire-precisiemodule kan rationale getallen van strings ontleden zoals "123/123", maar niet "123.123", "123e123", "0x1.23p-1" alsof ze kunnen worden weergegeven in C.

Achtergrond: ik waardeer de analyse van C-programma's met behulp van CIL .

Dubbele literalen van elke grootte en float-letterwoorden met een numerieke waarde die in 64 bit past, worden altijd correct weergegeven. Door af te ronden van dubbele naar enkele precisie, kan ik ook double reproduceren afrondingsfouten .

2
Wat is een "C drijvende-komma aantal" in uw geest/context?
toegevoegd de auteur Kerrek SB, de bron
Zie bewerken. Ik moet de numerieke waarde van drijvende-komma-letterwoorden in C-code krijgen. Het ontleden is onafhankelijk van hoe lang de registers eigenlijk zijn.
toegevoegd de auteur ralf, de bron
De vraag bijgewerkt. Zelfs als ik single-precision floats goed heb, moet ik literals parseren met waarden groter dan 64 bit.
toegevoegd de auteur ralf, de bron
De hoek van Nitpicker: eigenlijk is slechts op enkele platforms lang dubbel 128 bit; op x86 is het meestal 80 bit (de interne precisie van de x87 FPU), en voor VC ++ is het gewoon een normale double ( meer info ).
toegevoegd de auteur Matteo Italia, de bron
Ik weet niet helemaal zeker wat je bedoelt met het ontleden van de cijfers. Bedoel je dat je alleen maar wilt verifiëren dat de numerieke constanten goed zijn gevormd? Of wil je ze naar een numerieke waarde vertalen? Dan hebt u een probleem met de weergave en een probleem met de parsering.
toegevoegd de auteur Jeffrey Scofield, de bron
Ik vind het een beetje vreemd dat iemand die vooral geïnteresseerd is in dubbele afronding, iets zegt als: "OCAML's zweeftype is 64 bit, dus de float_of_string-functie werkt prima voor C's float- en double-typen." Functie float_to_string werkt niet voor single-precision floats, natuurlijk: blog.frama-c.com/index.php?post/2010/11/20/ & hellip;
toegevoegd de auteur Pascal Cuoq, de bron
Misschien wil je ook weten dat strtod() en strtof() (de eerst gebruikte door OCaml, de tweede die je voor jezelf kunt gebruiken) al lang bestaande bugs op Linux hebben die toon op die nummers die de dubbele afrondingsfouten zouden vertonen. Ik heb onlangs hetzelfde probleem opgelost, maar ik heb long double niet gedaan, dus ik weet niet zeker of je geïnteresseerd bent in mijn oplossing. Plus het is in Frama-C, met zijn gemeenschappelijke interface-laag boven Big_int/Zarith.
toegevoegd de auteur Pascal Cuoq, de bron

2 antwoord

I wrote my answer in the form of a blog post

Om een ​​paar van de punten hier samen te vatten: je zou een interface kunnen maken tussen strtold() en strtof() van OCaml. Voor de eerstgenoemde zou je moeten overwegen hoe je het resultaat dat het produceert opslaat, omdat er alleen een punt is als lang dubbel groter is dan dubbel op je host architectuur. Er rest nog het probleem dat deze functies fouten bevatten in een van de meest gebruikte C-bibliotheken. Heel licht met fouten, maar met fouten voor precies de voorbeelden die interessant zullen zijn als je dit doet om dubbele afronding te bestuderen.

Een andere manier is om je eigen functie te schrijven, te beginnen met another plaatsen in de blog waarnaar je verwijst.

Ten slotte is de uitdrukking "Zelfs het krijgen van single-precision floats right vereist dat ik literals moet parseren met waarden groter dan 64 bit" die je in de comments gebruikt nog steeds een vreemde manier om het te zeggen. De tussenliggende indeling (en) waarin u de weergave van een float met enkele precisie kunt analyseren voordat u deze omgeeft tot enkele precisie moet verliesloos zijn, anders krijgt u dubbele afronding. Dubbele afronding kan meer of minder moeilijk zijn om te exposeren, afhankelijk van de precisie van het verliesgevende tussenformaat, maar het gebruik van 80-bits of 128-bits binaire floating-point-indelingen zal het probleem niet verwijderen, maar het subtieler maken. In het eenvoudige algoritme dat ik aanraad, is het tussenformaat een fractie van twee multiprecision-getallen.

2
toegevoegd

Ik zie de vraag niet in deze vraag :)

Ervan uitgaande dat je een ocaml-parser nodig hebt voor "C float literals" - het antwoord is - schrijf er zelf een, het is niet erg moeilijk en je zult strikte controle hebben over de implementatiedetails en wat letterlijk "C float letterlijk" betekent.

0
toegevoegd
Je hebt gelijk, er is niet echt een vraag meer. Ik hoopte dat er een gemakkelijkere manier zou zijn dan zelf een parser te schrijven.
toegevoegd de auteur ralf, de bron
Ik denk het niet, want je taak is nogal specifiek.
toegevoegd de auteur ygrek, de bron