MySQL的`FLOAT`实际上存储的是`DOUBLE`类型吗?

huangapple go评论73阅读模式
英文:

MySQL `FLOAT` actually stores `DOUBLE`?

问题

我在MySQL中有以下表格:

create table testfloat (f float unsigned);
insert into testfloat values (70.99);

这应该将70.99的32位浮点数存储到表格中。

我有以下代码从数据库中读取该值:

package main

import (
	"database/sql"
	"fmt"
	"strconv"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	db, err := sql.Open("mysql", "root@(localhost)/test")
	if err != nil {
		panic(err)
	}

	rows, err := db.Query("select f from testfloat;")
	if err != nil {
		panic(err)
	}

	fmt.Printf("32-bit 70.99: %s\n", strconv.FormatFloat(70.99, 'f', 50, 32))
	fmt.Printf("64-bit 70.99: %s\n", strconv.FormatFloat(70.99, 'f', 50, 64))
	fmt.Printf("64-bit 70.99 cast from 32-bit 70.99: %s\n", strconv.FormatFloat(float64(float32(70.99)), 'f', 50, 64))

	var f float64
	for rows.Next() {
		if err := rows.Scan(&f); err != nil {
			panic(err)
		}
		fmt.Printf("DB 70.99: %.50f\n", f)
	}
}

输出结果为:

32-bit 70.99: 70.98999786376953125000000000000000000000000000000000
64-bit 70.99: 70.98999999999999488409230252727866172790527343750000
64-bit 70.99 cast from 32-bit 70.99: 70.98999786376953125000000000000000000000000000000000
DB 70.99: 70.98999999999999488409230252727866172790527343750000

如果数据库将浮点数存储为32位,则数据库输出应该等于第三行。但实际上它等于第二行。所以似乎它存储了一个64位浮点数,尽管我指定了float作为类型。为什么会这样呢?

英文:

I have the following table in MySQL:

create table testfloat (f float unsigned);
insert into testfloat values (70.99);

So this should store 32-bit float equivalent of 70.99 into the table.

I have the following code to read the value from DB:

package main

import (
	"database/sql"
	"fmt"
	"strconv"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	db, err := sql.Open("mysql", "root@(localhost)/test")
	if err != nil {
		panic(err)
	}

	rows, err := db.Query("select f from testfloat;")
	if err != nil {
		panic(err)
	}

	fmt.Printf("32-bit 70.99: %s\n", strconv.FormatFloat(70.99, 'f', 50, 32))
	fmt.Printf("64-bit 70.99: %s\n", strconv.FormatFloat(70.99, 'f', 50, 64))
	fmt.Printf("64-bit 70.99 cast from 32-bit 70.99: %s\n", strconv.FormatFloat(float64(float32(70.99)), 'f', 50, 64))

	var f float64
	for rows.Next() {
		if err := rows.Scan(&f); err != nil {
			panic(err)
		}
		fmt.Printf("DB 70.99: %.50f\n", f)
	}
}

The output is:

32-bit 70.99: 70.98999786376953125000000000000000000000000000000000
64-bit 70.99: 70.98999999999999488409230252727866172790527343750000
64-bit 70.99 cast from 32-bit 70.99: 70.98999786376953125000000000000000000000000000000000
DB 70.99: 70.98999999999999488409230252727866172790527343750000

If the DB was storing the float as 32 bits, then the DB output should be equal to the third line. But instead it's equal to the 2nd line. So it seems that it's storing a 64-bit float even though I specified float as the type. Why is this the case?

答案1

得分: 2

创建表test(f float unsigned,d double unsigned);
插入到test中的值为(70.99,70.99);
从test中选择f,d,f=d;
f d f=d
70.99 70.99 0

如您所见,浮点数和双精度列在视觉上存储相同的值,但它们并不相等。

您在代码中看到的效果是由Go而不是MySQL产生的。MySQL以文本格式(实际上是二进制流)返回输出行集(以及其中的数值),而不是作为二进制数值 - 您可以使用嗅探器进行测试。


<details>
<summary>英文:</summary>

create table test (f float unsigned, d double unsigned);
insert into test values (70.99, 70.99);
SELECT f, d, f=d FROM test;


| f | d | f=d |
|--:|--:|----:|
| 70.99 | 70.99 | 0 |

[fiddle](https://dbfiddle.uk/BExauzbD)

As you can see float and double columns stores the same value visually but they are not equal.

The effect which you see in your code is produced by Go, not by MySQL. MySQL returns the output rowset (and numeric values in it) in textual format (really - as binary stream), not as binary numbers - you may test this with a sniffer.

</details>



huangapple
  • 本文由 发表于 2022年11月11日 12:19:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/74397975.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定